git-mob-mcp-server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +89 -0
  3. package/dist/clients/gitMobClient.js +38 -0
  4. package/dist/clients/gitMobClient.test.js +114 -0
  5. package/dist/gitMobServerFactory.js +34 -0
  6. package/dist/gitMobServerFactory.test.js +58 -0
  7. package/dist/helpers/index.js +4 -0
  8. package/dist/helpers/registerGitMobResource.js +4 -0
  9. package/dist/helpers/registerGitMobResource.test.js +36 -0
  10. package/dist/helpers/registerGitMobResourceAsTool.js +24 -0
  11. package/dist/helpers/registerGitMobResourceAsTool.test.js +63 -0
  12. package/dist/helpers/registerGitMobTool.js +9 -0
  13. package/dist/helpers/registerGitMobTool.test.js +40 -0
  14. package/dist/helpers/runCliCommand.js +21 -0
  15. package/dist/helpers/runCliCommand.test.js +38 -0
  16. package/dist/index.js +8 -0
  17. package/dist/index.test.js +22 -0
  18. package/dist/resources/gitMobHelp.js +29 -0
  19. package/dist/resources/gitMobHelp.test.js +23 -0
  20. package/dist/resources/gitMobVersion.js +27 -0
  21. package/dist/resources/gitMobVersion.test.js +19 -0
  22. package/dist/resources/index.js +5 -0
  23. package/dist/resources/mobSessionCoauthorTrailers.js +39 -0
  24. package/dist/resources/mobSessionCoauthorTrailers.test.js +22 -0
  25. package/dist/resources/mobSessionCoauthors.js +40 -0
  26. package/dist/resources/mobSessionCoauthors.test.js +21 -0
  27. package/dist/resources/teamMembers.js +41 -0
  28. package/dist/resources/teamMembers.test.js +22 -0
  29. package/dist/tools/addTeamMember.js +31 -0
  30. package/dist/tools/addTeamMember.test.js +33 -0
  31. package/dist/tools/clearMobSession.js +23 -0
  32. package/dist/tools/clearMobSession.test.js +25 -0
  33. package/dist/tools/deleteTeamMember.js +28 -0
  34. package/dist/tools/deleteTeamMember.test.js +30 -0
  35. package/dist/tools/index.js +6 -0
  36. package/dist/tools/setMobSessionCoauthors.js +29 -0
  37. package/dist/tools/setMobSessionCoauthors.test.js +31 -0
  38. package/dist/tools/setupGitMobGlobally.js +27 -0
  39. package/dist/tools/setupGitMobGlobally.test.js +29 -0
  40. package/dist/tools/setupGitMobLocally.js +28 -0
  41. package/dist/tools/setupGitMobLocally.test.js +30 -0
  42. package/dist/types/GitMobResource.js +1 -0
  43. package/dist/types/GitMobTool.js +1 -0
  44. package/package.json +88 -0
@@ -0,0 +1,29 @@
1
+ import { ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { getHelp } from "../clients/gitMobClient.js";
3
+ const name = "git_mob_help";
4
+ const template = new ResourceTemplate("gitmob://help", { list: undefined });
5
+ const metadata = {
6
+ description: "Displays general help and usage information for the Git Mob CLI. " +
7
+ "You can optionally provide a command ('setup', 'coauthor', or 'help') " +
8
+ "to get detailed help for that specific command.",
9
+ mimeType: "text/plain",
10
+ };
11
+ const readCallback = async (uri, { command }) => {
12
+ const { ok, value } = await getHelp(command);
13
+ return {
14
+ isError: !ok,
15
+ contents: [
16
+ {
17
+ uri: uri.href,
18
+ text: value,
19
+ },
20
+ ],
21
+ };
22
+ };
23
+ const resource = {
24
+ name,
25
+ template,
26
+ metadata,
27
+ readCallback,
28
+ };
29
+ export default resource;
@@ -0,0 +1,23 @@
1
+ import resource from "./gitMobHelp";
2
+ import { describe, it, expect } from "@jest/globals";
3
+ import { ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ describe("[resources] gitMobHelp", () => {
5
+ it("should have correct name", () => {
6
+ expect(resource.name).toBe("git_mob_help");
7
+ });
8
+ it("should have correct template", () => {
9
+ const template = new ResourceTemplate("gitmob://help", {
10
+ list: undefined,
11
+ });
12
+ expect(resource.template).toEqual(template);
13
+ });
14
+ it("should have correct metadata", () => {
15
+ const metadata = {
16
+ description: "Displays general help and usage information for the Git Mob CLI. " +
17
+ "You can optionally provide a command ('setup', 'coauthor', or 'help') " +
18
+ "to get detailed help for that specific command.",
19
+ mimeType: "text/plain",
20
+ };
21
+ expect(resource.metadata).toEqual(metadata);
22
+ });
23
+ });
@@ -0,0 +1,27 @@
1
+ import { ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { getVersion } from "../clients/gitMobClient.js";
3
+ const name = "git_mob_version";
4
+ const template = new ResourceTemplate("gitmob://version", { list: undefined });
5
+ const metadata = {
6
+ description: "The installed version of the Git Mob CLI.",
7
+ mimeType: "text/plain",
8
+ };
9
+ const readCallback = async (uri) => {
10
+ const { ok, value } = await getVersion();
11
+ return {
12
+ isError: !ok,
13
+ contents: [
14
+ {
15
+ uri: uri.href,
16
+ text: value,
17
+ },
18
+ ],
19
+ };
20
+ };
21
+ const resource = {
22
+ name,
23
+ template,
24
+ metadata,
25
+ readCallback,
26
+ };
27
+ export default resource;
@@ -0,0 +1,19 @@
1
+ import resource from "./gitMobVersion";
2
+ import { describe, it, expect } from "@jest/globals";
3
+ import { ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ describe("[resources] gitMobVersion", () => {
5
+ it("should have correct name", () => {
6
+ expect(resource.name).toBe("git_mob_version");
7
+ });
8
+ it("should have correct template", () => {
9
+ const template = new ResourceTemplate("gitmob://version", { list: undefined });
10
+ expect(resource.template).toEqual(template);
11
+ });
12
+ it("should have correct metadata", () => {
13
+ const metadata = {
14
+ description: "The installed version of the Git Mob CLI.",
15
+ mimeType: "text/plain",
16
+ };
17
+ expect(resource.metadata).toEqual(metadata);
18
+ });
19
+ });
@@ -0,0 +1,5 @@
1
+ export { default as gitMobVersion } from "./gitMobVersion.js";
2
+ export { default as gitMobHelp } from "./gitMobHelp.js";
3
+ export { default as teamMembers } from "./teamMembers.js";
4
+ export { default as mobSessionCoauthors } from "./mobSessionCoauthors.js";
5
+ export { default as mobSessionCoauthorTrailers } from "./mobSessionCoauthorTrailers.js";
@@ -0,0 +1,39 @@
1
+ import { ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { listMobSessionCoauthorTrailers } from "../clients/gitMobClient.js";
3
+ const name = "mob_session_coauthor_trailers";
4
+ const template = new ResourceTemplate("gitmob://mob-session-coauthor-trailers", { list: undefined });
5
+ const metadata = {
6
+ description: "List of the git Co-authored-by trailers for the coauthors " +
7
+ "currently included in the active mob or pairing session. " +
8
+ "If Git Mob is setup, these Co-authored-by trailers will be automatically " +
9
+ "added to the commit's message when making commits during the session.",
10
+ mimeType: "text/plain",
11
+ };
12
+ const readCallback = async (uri) => {
13
+ const { ok, value } = await listMobSessionCoauthorTrailers();
14
+ if (!ok) {
15
+ return {
16
+ isError: true,
17
+ contents: [
18
+ {
19
+ uri: uri.href,
20
+ text: value,
21
+ },
22
+ ],
23
+ };
24
+ }
25
+ const lines = value.split("\n").filter((line) => line.trim() !== "");
26
+ return {
27
+ contents: lines.map((line) => ({
28
+ uri: uri.href,
29
+ text: line,
30
+ })),
31
+ };
32
+ };
33
+ const resource = {
34
+ name,
35
+ template,
36
+ metadata,
37
+ readCallback,
38
+ };
39
+ export default resource;
@@ -0,0 +1,22 @@
1
+ import resource from "./mobSessionCoauthorTrailers";
2
+ import { describe, it, expect } from "@jest/globals";
3
+ import { ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ describe("[resources] mobSessionCoauthorTrailers", () => {
5
+ it("should have correct name", () => {
6
+ expect(resource.name).toBe("mob_session_coauthor_trailers");
7
+ });
8
+ it("should have correct template", () => {
9
+ const template = new ResourceTemplate("gitmob://mob-session-coauthor-trailers", { list: undefined });
10
+ expect(resource.template).toEqual(template);
11
+ });
12
+ it("should have correct metadata", () => {
13
+ const metadata = {
14
+ description: "List of the git Co-authored-by trailers for the coauthors " +
15
+ "currently included in the active mob or pairing session. " +
16
+ "If Git Mob is setup, these Co-authored-by trailers will be automatically " +
17
+ "added to the commit's message when making commits during the session.",
18
+ mimeType: "text/plain",
19
+ };
20
+ expect(resource.metadata).toEqual(metadata);
21
+ });
22
+ });
@@ -0,0 +1,40 @@
1
+ import { ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { listMobSessionCoauthors } from "../clients/gitMobClient.js";
3
+ const name = "mob_session_coauthors";
4
+ const template = new ResourceTemplate("gitmob://mob-session-coauthors", {
5
+ list: undefined,
6
+ });
7
+ const metadata = {
8
+ description: "List of all coauthors currently included in the active mob or pairing session. " +
9
+ "If Git Mob is setup, these coauthors will be automatically added as " +
10
+ "Co-authored-by trailers to the commit's message when making commits during the session.",
11
+ mimeType: "text/plain",
12
+ };
13
+ const readCallback = async (uri) => {
14
+ const { ok, value } = await listMobSessionCoauthors();
15
+ if (!ok) {
16
+ return {
17
+ isError: true,
18
+ contents: [
19
+ {
20
+ uri: uri.href,
21
+ text: value,
22
+ },
23
+ ],
24
+ };
25
+ }
26
+ const lines = value.split("\n").filter((line) => line.trim() !== "");
27
+ return {
28
+ contents: lines.map((line) => ({
29
+ uri: uri.href,
30
+ text: line,
31
+ })),
32
+ };
33
+ };
34
+ const resource = {
35
+ name,
36
+ template,
37
+ metadata,
38
+ readCallback,
39
+ };
40
+ export default resource;
@@ -0,0 +1,21 @@
1
+ import resource from "./mobSessionCoauthors";
2
+ import { describe, it, expect } from "@jest/globals";
3
+ import { ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ describe("[resources] mobSessionCoauthors", () => {
5
+ it("should have correct name", () => {
6
+ expect(resource.name).toBe("mob_session_coauthors");
7
+ });
8
+ it("should have correct template", () => {
9
+ const template = new ResourceTemplate("gitmob://mob-session-coauthors", { list: undefined });
10
+ expect(resource.template).toEqual(template);
11
+ });
12
+ it("should have correct metadata", () => {
13
+ const metadata = {
14
+ description: "List of all coauthors currently included in the active mob or pairing session. " +
15
+ "If Git Mob is setup, these coauthors will be automatically added as " +
16
+ "Co-authored-by trailers to the commit's message when making commits during the session.",
17
+ mimeType: "text/plain",
18
+ };
19
+ expect(resource.metadata).toEqual(metadata);
20
+ });
21
+ });
@@ -0,0 +1,41 @@
1
+ import { ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { listCoauthors } from "../clients/gitMobClient.js";
3
+ const name = "team_members";
4
+ const template = new ResourceTemplate("gitmob://team-members", {
5
+ list: undefined,
6
+ });
7
+ const metadata = {
8
+ description: "List of all the team members that have been added to Git Mob. " +
9
+ "The team members can then be used in pairing / mobbing sessions as coauthors." +
10
+ "Each entry is formatted as: <key> <name> <email>." +
11
+ "Ask the user which team member(s) they want to pair or mob with.",
12
+ mimeType: "text/plain",
13
+ };
14
+ const readCallback = async (uri) => {
15
+ const { ok, value } = await listCoauthors();
16
+ if (!ok) {
17
+ return {
18
+ isError: true,
19
+ contents: [
20
+ {
21
+ uri: uri.href,
22
+ text: value,
23
+ },
24
+ ],
25
+ };
26
+ }
27
+ const lines = (value || "").split("\n").filter((line) => line.trim() !== "");
28
+ return {
29
+ contents: lines.map((line) => ({
30
+ uri: uri.href,
31
+ text: line,
32
+ })),
33
+ };
34
+ };
35
+ const resource = {
36
+ name,
37
+ template,
38
+ metadata,
39
+ readCallback,
40
+ };
41
+ export default resource;
@@ -0,0 +1,22 @@
1
+ import resource from "./teamMembers";
2
+ import { describe, it, expect } from "@jest/globals";
3
+ import { ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ describe("[resources] teamMembers", () => {
5
+ it("should have correct name", () => {
6
+ expect(resource.name).toBe("team_members");
7
+ });
8
+ it("should have correct template", () => {
9
+ const template = new ResourceTemplate("gitmob://team-members", { list: undefined });
10
+ expect(resource.template).toEqual(template);
11
+ });
12
+ it("should have correct metadata", () => {
13
+ const metadata = {
14
+ description: "List of all the team members that have been added to Git Mob. " +
15
+ "The team members can then be used in pairing / mobbing sessions as coauthors." +
16
+ "Each entry is formatted as: <key> <name> <email>." +
17
+ "Ask the user which team member(s) they want to pair or mob with.",
18
+ mimeType: "text/plain",
19
+ };
20
+ expect(resource.metadata).toEqual(metadata);
21
+ });
22
+ });
@@ -0,0 +1,31 @@
1
+ import { z } from "zod";
2
+ import { addCoauthor } from "../clients/gitMobClient.js";
3
+ const name = "add_team_member";
4
+ const description = "Adds a new team member using their key, name, and email. " +
5
+ "This member can then be used in a pairing or mobbing sessions as a cauthor. " +
6
+ "The first name is a good choice for the key." +
7
+ "Ask the user if they want mob or pair with this team member.";
8
+ const inputSchema = {
9
+ key: z.string(),
10
+ name: z.string(),
11
+ email: z.string(),
12
+ };
13
+ const annotations = {
14
+ title: "Add Team Member",
15
+ readOnlyHint: false,
16
+ destructiveHint: false,
17
+ idempotentHint: false,
18
+ openWorldHint: false,
19
+ };
20
+ const callback = async ({ key, name, email, }) => {
21
+ const { ok, value } = await addCoauthor(key, name, email);
22
+ return { isError: !ok, content: [{ type: "text", text: value }] };
23
+ };
24
+ const tool = {
25
+ name,
26
+ description,
27
+ inputSchema,
28
+ annotations,
29
+ callback,
30
+ };
31
+ export default tool;
@@ -0,0 +1,33 @@
1
+ import { z } from "zod";
2
+ import tool from "./addTeamMember.js";
3
+ import { describe, it, expect } from "@jest/globals";
4
+ describe("[tools] addTeamMember", () => {
5
+ it("should have correct name", () => {
6
+ expect(tool.name).toBe("add_team_member");
7
+ });
8
+ it("should have correct description", () => {
9
+ const description = "Adds a new team member using their key, name, and email. " +
10
+ "This member can then be used in a pairing or mobbing sessions as a cauthor. " +
11
+ "The first name is a good choice for the key." +
12
+ "Ask the user if they want mob or pair with this team member.";
13
+ expect(tool.description).toBe(description);
14
+ });
15
+ it("should have correct input schema", () => {
16
+ const inputSchema = {
17
+ key: z.string(),
18
+ name: z.string(),
19
+ email: z.string(),
20
+ };
21
+ expect(JSON.stringify(tool.inputSchema)).toEqual(JSON.stringify(inputSchema));
22
+ });
23
+ it("should have correct annotations", () => {
24
+ const annotations = {
25
+ title: "Add Team Member",
26
+ readOnlyHint: false,
27
+ destructiveHint: false,
28
+ idempotentHint: false,
29
+ openWorldHint: false,
30
+ };
31
+ expect(tool.annotations).toEqual(annotations);
32
+ });
33
+ });
@@ -0,0 +1,23 @@
1
+ import { clearMobSession } from "../clients/gitMobClient.js";
2
+ const name = "clear_mob_session";
3
+ const description = "Clears the active mob or pairing session.";
4
+ const inputSchema = {};
5
+ const annotations = {
6
+ title: "Clear Mob Session",
7
+ readOnlyHint: false,
8
+ destructiveHint: false,
9
+ idempotentHint: true,
10
+ openWorldHint: false,
11
+ };
12
+ const callback = async () => {
13
+ const { ok, value } = await clearMobSession();
14
+ return { isError: !ok, content: [{ type: "text", text: value }] };
15
+ };
16
+ const tool = {
17
+ name,
18
+ description,
19
+ inputSchema,
20
+ annotations,
21
+ callback,
22
+ };
23
+ export default tool;
@@ -0,0 +1,25 @@
1
+ import tool from "./clearMobSession.js";
2
+ import { describe, it, expect } from "@jest/globals";
3
+ describe("[tools] clearMobSession", () => {
4
+ it("should have correct name", () => {
5
+ expect(tool.name).toBe("clear_mob_session");
6
+ });
7
+ it("should have correct description", () => {
8
+ const description = "Clears the active mob or pairing session.";
9
+ expect(tool.description).toBe(description);
10
+ });
11
+ it("should have correct input schema", () => {
12
+ const inputSchema = {};
13
+ expect(JSON.stringify(tool.inputSchema)).toEqual(JSON.stringify(inputSchema));
14
+ });
15
+ it("should have correct annotations", () => {
16
+ const annotations = {
17
+ title: "Clear Mob Session",
18
+ readOnlyHint: false,
19
+ destructiveHint: false,
20
+ idempotentHint: true,
21
+ openWorldHint: false,
22
+ };
23
+ expect(tool.annotations).toEqual(annotations);
24
+ });
25
+ });
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+ import { deleteCoauthor } from "../clients/gitMobClient.js";
3
+ const name = "delete_team_member";
4
+ const description = "Deletes a team member by their key. " +
5
+ "User can only delete a team member they have added previously. " +
6
+ "If user did not specify a key, show them list of existing team members and ask them to select one.";
7
+ const inputSchema = {
8
+ key: z.string(),
9
+ };
10
+ const annotations = {
11
+ title: "Delete Team Member",
12
+ readOnlyHint: false,
13
+ destructiveHint: true,
14
+ idempotentHint: true,
15
+ openWorldHint: false,
16
+ };
17
+ const callback = async ({ key }) => {
18
+ const { ok, value } = await deleteCoauthor(key);
19
+ return { isError: !ok, content: [{ type: "text", text: value }] };
20
+ };
21
+ const tool = {
22
+ name,
23
+ description,
24
+ inputSchema,
25
+ annotations,
26
+ callback,
27
+ };
28
+ export default tool;
@@ -0,0 +1,30 @@
1
+ import { z } from "zod";
2
+ import tool from "./deleteTeamMember.js";
3
+ import { describe, it, expect } from "@jest/globals";
4
+ describe("[tools] deleteTeamMember", () => {
5
+ it("should have correct name", () => {
6
+ expect(tool.name).toBe("delete_team_member");
7
+ });
8
+ it("should have correct description", () => {
9
+ const description = "Deletes a team member by their key. " +
10
+ "User can only delete a team member they have added previously. " +
11
+ "If user did not specify a key, show them list of existing team members and ask them to select one.";
12
+ expect(tool.description).toBe(description);
13
+ });
14
+ it("should have correct input schema", () => {
15
+ const inputSchema = {
16
+ key: z.string(),
17
+ };
18
+ expect(JSON.stringify(tool.inputSchema)).toEqual(JSON.stringify(inputSchema));
19
+ });
20
+ it("should have correct annotations", () => {
21
+ const annotations = {
22
+ title: "Delete Team Member",
23
+ readOnlyHint: false,
24
+ destructiveHint: true,
25
+ idempotentHint: true,
26
+ openWorldHint: false,
27
+ };
28
+ expect(tool.annotations).toEqual(annotations);
29
+ });
30
+ });
@@ -0,0 +1,6 @@
1
+ export { default as setupGitMobGlobally } from "./setupGitMobGlobally.js";
2
+ export { default as setupGitMobLocally } from "./setupGitMobLocally.js";
3
+ export { default as addTeamMember } from "./addTeamMember.js";
4
+ export { default as deleteTeamMember } from "./deleteTeamMember.js";
5
+ export { default as setMobSessionCoauthors } from "./setMobSessionCoauthors.js";
6
+ export { default as clearMobSession } from "./clearMobSession.js";
@@ -0,0 +1,29 @@
1
+ import { z } from "zod";
2
+ import { setMobSession } from "../clients/gitMobClient.js";
3
+ const name = "set_mob_session_coauthors";
4
+ const description = "Sets the active pairing or mob session by specifying the " +
5
+ "keys of the team members to include as coauthors. " +
6
+ "If Git Mob is setup, these coauthors will be automatically added as " +
7
+ "Co-authored-by trailers to the commit's message when making commits during the session.";
8
+ const inputSchema = {
9
+ coauthorKeys: z.array(z.string()).min(1),
10
+ };
11
+ const annotations = {
12
+ title: "Set Mob or Pairing Session Coauthors using Team Members",
13
+ readOnlyHint: false,
14
+ destructiveHint: true,
15
+ idempotentHint: true,
16
+ openWorldHint: false,
17
+ };
18
+ const callback = async ({ coauthorKeys }) => {
19
+ const { ok, value } = await setMobSession(coauthorKeys);
20
+ return { isError: !ok, content: [{ type: "text", text: value }] };
21
+ };
22
+ const tool = {
23
+ name,
24
+ description,
25
+ inputSchema,
26
+ annotations,
27
+ callback,
28
+ };
29
+ export default tool;
@@ -0,0 +1,31 @@
1
+ import { z } from "zod";
2
+ import tool from "./setMobSessionCoauthors.js";
3
+ import { describe, it, expect } from "@jest/globals";
4
+ describe("[tools] setMobSessionCoauthors", () => {
5
+ it("should have correct name", () => {
6
+ expect(tool.name).toBe("set_mob_session_coauthors");
7
+ });
8
+ it("should have correct description", () => {
9
+ const description = "Sets the active pairing or mob session by specifying the " +
10
+ "keys of the team members to include as coauthors. " +
11
+ "If Git Mob is setup, these coauthors will be automatically added as " +
12
+ "Co-authored-by trailers to the commit's message when making commits during the session.";
13
+ expect(tool.description).toBe(description);
14
+ });
15
+ it("should have correct input schema", () => {
16
+ const inputSchema = {
17
+ coauthorKeys: z.array(z.string()).min(1),
18
+ };
19
+ expect(JSON.stringify(tool.inputSchema)).toEqual(JSON.stringify(inputSchema));
20
+ });
21
+ it("should have correct annotations", () => {
22
+ const annotations = {
23
+ title: "Set Mob or Pairing Session Coauthors using Team Members",
24
+ readOnlyHint: false,
25
+ destructiveHint: true,
26
+ idempotentHint: true,
27
+ openWorldHint: false,
28
+ };
29
+ expect(tool.annotations).toEqual(annotations);
30
+ });
31
+ });
@@ -0,0 +1,27 @@
1
+ import { setupGlobal } from "../clients/gitMobClient.js";
2
+ const name = "setup_git_mob_globally";
3
+ const description = "Configures the Git Mob CLI globally for all repositories on your system. " +
4
+ "This one-time setup installs a global prepare-commit-msg git hook, which automatically " +
5
+ "appends Co-authored-by trailers to commit messages during mob or pairing sessions. " +
6
+ "If a repository overrides the core.hooksPath git configuration (e.g., when using " +
7
+ "Husky), the setupGitMobLocally tool needs to be invoked in addition to this. ";
8
+ const inputSchema = {};
9
+ const annotations = {
10
+ title: "Setup Git Mob Globally",
11
+ readOnlyHint: false,
12
+ destructiveHint: true,
13
+ idempotentHint: false,
14
+ openWorldHint: false,
15
+ };
16
+ const callback = async () => {
17
+ const { ok, value } = await setupGlobal();
18
+ return { isError: !ok, content: [{ type: "text", text: value }] };
19
+ };
20
+ const tool = {
21
+ name,
22
+ description,
23
+ inputSchema,
24
+ annotations,
25
+ callback,
26
+ };
27
+ export default tool;
@@ -0,0 +1,29 @@
1
+ import tool from "./setupGitMobGlobally.js";
2
+ import { describe, it, expect } from "@jest/globals";
3
+ describe("[tools] setupGitMobGlobally", () => {
4
+ it("should have correct name", () => {
5
+ expect(tool.name).toBe("setup_git_mob_globally");
6
+ });
7
+ it("should have correct description", () => {
8
+ const description = "Configures the Git Mob CLI globally for all repositories on your system. " +
9
+ "This one-time setup installs a global prepare-commit-msg git hook, which automatically " +
10
+ "appends Co-authored-by trailers to commit messages during mob or pairing sessions. " +
11
+ "If a repository overrides the core.hooksPath git configuration (e.g., when using " +
12
+ "Husky), the setupGitMobLocally tool needs to be invoked in addition to this. ";
13
+ expect(tool.description).toBe(description);
14
+ });
15
+ it("should have correct input schema", () => {
16
+ const inputSchema = {};
17
+ expect(JSON.stringify(tool.inputSchema)).toEqual(JSON.stringify(inputSchema));
18
+ });
19
+ it("should have correct annotations", () => {
20
+ const annotations = {
21
+ title: "Setup Git Mob Globally",
22
+ readOnlyHint: false,
23
+ destructiveHint: true,
24
+ idempotentHint: false,
25
+ openWorldHint: false,
26
+ };
27
+ expect(tool.annotations).toEqual(annotations);
28
+ });
29
+ });
@@ -0,0 +1,28 @@
1
+ import { setupLocal } from "../clients/gitMobClient.js";
2
+ const name = "setup_git_mob_locally";
3
+ const description = "Sets up the Git Mob CLI for the current repository by installing a local " +
4
+ "prepare-commit-msg git hook. This hook delegates to the global " +
5
+ "prepare-commit-msg hook configured by setupGitMobGlobally. Use this tool " +
6
+ "only if your repository overrides the core.hooksPath git " +
7
+ "configuration (e.g., when using Husky). Note: You must run " +
8
+ "setupGitMobGlobally at least once before using this tool.";
9
+ const inputSchema = {};
10
+ const annotations = {
11
+ title: "Setup Git Mob Locally",
12
+ readOnlyHint: false,
13
+ destructiveHint: true,
14
+ idempotentHint: false,
15
+ openWorldHint: false,
16
+ };
17
+ const callback = async () => {
18
+ const { ok, value } = await setupLocal();
19
+ return { isError: !ok, content: [{ type: "text", text: value }] };
20
+ };
21
+ const tool = {
22
+ name,
23
+ description,
24
+ inputSchema,
25
+ annotations,
26
+ callback,
27
+ };
28
+ export default tool;