Bläddra i källkod

feat: add Collaborator Management support #8

Implements full collaborator management functionality for Gogs repositories.

## Changes:
- Added GogsCollaborator type definition in types.ts
- Implemented 4 new client methods in gogs-client.ts:
  - listCollaborators(): Get all collaborators for a repository
  - checkCollaborator(): Check if user is a collaborator
  - addCollaborator(): Add user as collaborator with permissions
  - removeCollaborator(): Remove collaborator access
- Added 4 new MCP tools in server.ts:
  - list_collaborators
  - check_collaborator
  - add_collaborator
  - remove_collaborator
- Updated README.md with new Collaborator Management Tools section
- Moved Collaborators from "Not Yet Implemented" to "Implemented" in docs
- Updated CLAUDE.md with Collaborator Management category

All features tested and working correctly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
claude 9 månader sedan
förälder
incheckning
68de2ebc29
5 ändrade filer med 260 tillägg och 3 borttagningar
  1. 1 0
      CLAUDE.md
  2. 26 3
      README.md
  3. 47 0
      src/gogs-client.ts
  4. 172 0
      src/server.ts
  5. 14 0
      src/types.ts

+ 1 - 0
CLAUDE.md

@@ -36,6 +36,7 @@ The server exposes tools in these categories:
 - **Organization Management**: list_user_organizations, create_organization, list_public_organizations, get_organization, update_organization, add_organization_member
 - **Team Management**: list_organization_teams, create_team, get_team, add_team_member, remove_team_member
 - **Release Management**: list_releases
+- **Collaborator Management**: list_collaborators, check_collaborator, add_collaborator, remove_collaborator
 
 ## Development Commands
 

+ 26 - 3
README.md

@@ -572,6 +572,32 @@ List all releases for a repository. Returns release information including tag na
 
 **Note**: Currently only read-only access to releases is supported. Create, update, and delete operations are not available in the Gogs API v1.
 
+### Collaborator Management Tools
+
+#### `list_collaborators`
+List all collaborators for a repository. Returns user information including username, full name, email, avatar URL, and their permission levels (admin, push, pull).
+- `owner` (string, required): Repository owner username
+- `repo` (string, required): Repository name
+
+#### `check_collaborator`
+Check if a user is a collaborator on a repository. Returns a boolean indicating whether the specified user has collaborator access.
+- `owner` (string, required): Repository owner username
+- `repo` (string, required): Repository name
+- `username` (string, required): Username to check for collaborator status
+
+#### `add_collaborator`
+Add a user as a collaborator to a repository with specified permissions.
+- `owner` (string, required): Repository owner username
+- `repo` (string, required): Repository name
+- `username` (string, required): Username to add as collaborator
+- `permission` (string, optional): Permission level - 'read', 'write', or 'admin' (default: 'write')
+
+#### `remove_collaborator`
+Remove a user's collaborator access from a repository.
+- `owner` (string, required): Repository owner username
+- `repo` (string, required): Repository name
+- `username` (string, required): Username to remove as collaborator
+
 ## Documented but Not Yet Implemented API Endpoints
 
 The following Gogs API v1 endpoints are officially documented but not yet implemented in this MCP server. These represent potential features for future development:
@@ -599,9 +625,6 @@ The following Gogs API v1 endpoints are officially documented but not yet implem
 | **Webhooks** | `/repos/:username/:reponame/hooks` | POST | Create a hook | [Link](https://github.com/gogs/docs-api/blob/master/Repositories/Webhooks.md) |
 | **Webhooks** | `/repos/:username/:reponame/hooks/:id` | PATCH | Edit a hook | [Link](https://github.com/gogs/docs-api/blob/master/Repositories/Webhooks.md) |
 | **Webhooks** | `/repos/:username/:reponame/hooks/:id` | DELETE | Delete a hook | [Link](https://github.com/gogs/docs-api/blob/master/Repositories/Webhooks.md) |
-| **Collaborators** | `/repos/:username/:reponame/collaborators` | GET | Get collaborators | [Link](https://github.com/gogs/docs-api/blob/master/Repositories/Collaborators.md) |
-| **Collaborators** | `/repos/:username/:reponame/collaborators/:collaborator` | PUT | Add user as a collaborator | [Link](https://github.com/gogs/docs-api/blob/master/Repositories/Collaborators.md) |
-| **Collaborators** | `/repos/:username/:reponame/collaborators/:collaborator` | DELETE | Delete collaborator | [Link](https://github.com/gogs/docs-api/blob/master/Repositories/Collaborators.md) |
 
 ### Contributing New Endpoints
 

+ 47 - 0
src/gogs-client.ts

@@ -19,6 +19,7 @@ import type {
   GogsTeam,
   GogsTree,
   GogsRelease,
+  GogsCollaborator,
 } from './types.js';
 
 export class GogsClient {
@@ -559,4 +560,50 @@ export class GogsClient {
     const response = await this.client.get<GogsRelease[]>(`/repos/${owner}/${repo}/releases`);
     return response.data;
   }
+
+  /**
+   * List collaborators for a repository
+   */
+  async listCollaborators(owner: string, repo: string): Promise<GogsCollaborator[]> {
+    const response = await this.client.get<GogsCollaborator[]>(
+      `/repos/${owner}/${repo}/collaborators`
+    );
+    return response.data;
+  }
+
+  /**
+   * Check if a user is a collaborator
+   */
+  async checkCollaborator(owner: string, repo: string, username: string): Promise<boolean> {
+    try {
+      await this.client.get(`/repos/${owner}/${repo}/collaborators/${username}`);
+      return true;
+    } catch (error) {
+      if (axios.isAxiosError(error) && error.response?.status === 404) {
+        return false;
+      }
+      throw error;
+    }
+  }
+
+  /**
+   * Add a collaborator to a repository
+   */
+  async addCollaborator(
+    owner: string,
+    repo: string,
+    username: string,
+    permission?: 'read' | 'write' | 'admin'
+  ): Promise<void> {
+    await this.client.put(`/repos/${owner}/${repo}/collaborators/${username}`, {
+      permission: permission || 'write',
+    });
+  }
+
+  /**
+   * Remove a collaborator from a repository
+   */
+  async removeCollaborator(owner: string, repo: string, username: string): Promise<void> {
+    await this.client.delete(`/repos/${owner}/${repo}/collaborators/${username}`);
+  }
 }

+ 172 - 0
src/server.ts

@@ -268,6 +268,30 @@ const ListReleasesSchema = z.object({
   repo: z.string().describe('Repository name'),
 });
 
+const ListCollaboratorsSchema = z.object({
+  owner: z.string().describe('Repository owner username'),
+  repo: z.string().describe('Repository name'),
+});
+
+const CheckCollaboratorSchema = z.object({
+  owner: z.string().describe('Repository owner username'),
+  repo: z.string().describe('Repository name'),
+  username: z.string().describe('Username to check for collaborator status'),
+});
+
+const AddCollaboratorSchema = z.object({
+  owner: z.string().describe('Repository owner username'),
+  repo: z.string().describe('Repository name'),
+  username: z.string().describe('Username to add as collaborator'),
+  permission: z.enum(['read', 'write', 'admin']).optional().describe('Permission level (default: write)'),
+});
+
+const RemoveCollaboratorSchema = z.object({
+  owner: z.string().describe('Repository owner username'),
+  repo: z.string().describe('Repository name'),
+  username: z.string().describe('Username to remove as collaborator'),
+});
+
 /**
  * Create and configure an MCP server with all tools and handlers
  */
@@ -1256,6 +1280,95 @@ export function createMcpServer(gogsClient: GogsClient): Server {
             required: ['owner', 'repo'],
           },
         },
+        {
+          name: 'list_collaborators',
+          description: 'List all collaborators for a repository',
+          inputSchema: {
+            type: 'object',
+            properties: {
+              owner: {
+                type: 'string',
+                description: 'Repository owner username',
+              },
+              repo: {
+                type: 'string',
+                description: 'Repository name',
+              },
+            },
+            required: ['owner', 'repo'],
+          },
+        },
+        {
+          name: 'check_collaborator',
+          description: 'Check if a user is a collaborator on a repository',
+          inputSchema: {
+            type: 'object',
+            properties: {
+              owner: {
+                type: 'string',
+                description: 'Repository owner username',
+              },
+              repo: {
+                type: 'string',
+                description: 'Repository name',
+              },
+              username: {
+                type: 'string',
+                description: 'Username to check for collaborator status',
+              },
+            },
+            required: ['owner', 'repo', 'username'],
+          },
+        },
+        {
+          name: 'add_collaborator',
+          description: 'Add a collaborator to a repository',
+          inputSchema: {
+            type: 'object',
+            properties: {
+              owner: {
+                type: 'string',
+                description: 'Repository owner username',
+              },
+              repo: {
+                type: 'string',
+                description: 'Repository name',
+              },
+              username: {
+                type: 'string',
+                description: 'Username to add as collaborator',
+              },
+              permission: {
+                type: 'string',
+                enum: ['read', 'write', 'admin'],
+                description: 'Permission level (default: write)',
+              },
+            },
+            required: ['owner', 'repo', 'username'],
+          },
+        },
+        {
+          name: 'remove_collaborator',
+          description: 'Remove a collaborator from a repository',
+          inputSchema: {
+            type: 'object',
+            properties: {
+              owner: {
+                type: 'string',
+                description: 'Repository owner username',
+              },
+              repo: {
+                type: 'string',
+                description: 'Repository name',
+              },
+              username: {
+                type: 'string',
+                description: 'Username to remove as collaborator',
+              },
+            },
+            required: ['owner', 'repo', 'username'],
+          },
+        },
       ],
     };
   });
@@ -1854,6 +1967,65 @@ export function createMcpServer(gogsClient: GogsClient): Server {
           };
         }
 
+        case 'list_collaborators': {
+          const { owner, repo } = ListCollaboratorsSchema.parse(args);
+          const collaborators = await gogsClient.listCollaborators(owner, repo);
+          return {
+            content: [
+              {
+                type: 'text',
+                text: JSON.stringify(collaborators, null, 2),
+              },
+            ],
+          };
+        }
+
+        case 'check_collaborator': {
+          const { owner, repo, username } = CheckCollaboratorSchema.parse(args);
+          const isCollaborator = await gogsClient.checkCollaborator(owner, repo, username);
+          return {
+            content: [
+              {
+                type: 'text',
+                text: JSON.stringify({ isCollaborator, username, repository: `${owner}/${repo}` }, null, 2),
+              },
+            ],
+          };
+        }
+
+        case 'add_collaborator': {
+          const { owner, repo, username, permission } = AddCollaboratorSchema.parse(args);
+          await gogsClient.addCollaborator(owner, repo, username, permission);
+          return {
+            content: [
+              {
+                type: 'text',
+                text: JSON.stringify({
+                  success: true,
+                  message: `Successfully added ${username} as collaborator to ${owner}/${repo}`,
+                  permission: permission || 'write'
+                }, null, 2),
+              },
+            ],
+          };
+        }
+
+        case 'remove_collaborator': {
+          const { owner, repo, username } = RemoveCollaboratorSchema.parse(args);
+          await gogsClient.removeCollaborator(owner, repo, username);
+          return {
+            content: [
+              {
+                type: 'text',
+                text: JSON.stringify({
+                  success: true,
+                  message: `Successfully removed ${username} as collaborator from ${owner}/${repo}`
+                }, null, 2),
+              },
+            ],
+          };
+        }
+
         default:
           throw new Error(`Unknown tool: ${name}`);
       }

+ 14 - 0
src/types.ts

@@ -182,3 +182,17 @@ export interface GogsRelease {
   published_at: string;
   assets: GogsReleaseAttachment[];
 }
+
+export interface GogsCollaborator {
+  id: number;
+  username: string;
+  login: string;
+  full_name: string;
+  email: string;
+  avatar_url: string;
+  permissions: {
+    admin: boolean;
+    push: boolean;
+    pull: boolean;
+  };
+}