restricted-github-mcp 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.
package/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # GitHub MCP Server (Controlled)
2
+
3
+ Ce serveur implémente le **Model Context Protocol (MCP)** pour permettre à des agents IA (comme Cursor, Claude Desktop, etc.) d'interagir avec GitHub de manière sécurisée et contrôlée.
4
+
5
+ ## 🚀 Fonctionnalités
6
+
7
+ Le serveur expose plusieurs outils (tools) pour manipuler les dépôts GitHub :
8
+
9
+ - **`get_file_contents`** : Lire le contenu d'un fichier.
10
+ - **`git_push`** : Créer ou mettre à jour un fichier (Push).
11
+ - **`pull_request_create`** : Créer une Pull Request.
12
+ - **`list_issues`** : Lister les issues et PRs d'un dépôt.
13
+ - **`create_issue_comment`** : Ajouter un commentaire sur une issue ou PR.
14
+
15
+ ## 🔒 Sécurité et Contrôle
16
+
17
+ Le serveur est conçu avec un principe de contrôle strict via des variables d'environnement :
18
+
19
+ - **`ALLOWED_REPOS`** : Liste des dépôts (`propriétaire/nom`) que l'agent est autorisé à manipuler.
20
+ - **`ALLOWED_BRANCHES`** : Masques de branches autorisés pour les pushs (ex: `feature/*`, `mcp-*`).
21
+ - **`READ_ONLY`** : Si mis à `true`, toutes les actions d'écriture (push, PR, commentaires) sont désactivées.
22
+
23
+ ## 🛠️ Installation
24
+
25
+ 1. **Cloner le projet** (ou copier les fichiers).
26
+ 2. **Installer les dépendances** :
27
+ ```bash
28
+ npm install
29
+ ```
30
+ 3. **Configurer l'environnement** :
31
+ Créez un fichier `.env` à la racine (voir section Configuration ci-dessous).
32
+
33
+ ## ⚙️ Configuration
34
+
35
+ Créez un fichier `.env` avec les variables suivantes :
36
+
37
+ ```env
38
+ # Votre Token d'accès personnel GitHub (PAT)
39
+ GITHUB_TOKEN=ghp_xxxxxxxxxxxx
40
+
41
+ # Dépôts autorisés (séparés par des virgules)
42
+ ALLOWED_REPOS=votre-org/votre-repo,un-autre/depot
43
+
44
+ # Branches autorisées pour le push (supporte *)
45
+ ALLOWED_BRANCHES=main,develop,mcp-*
46
+
47
+ # Mode lecture seule (true/false)
48
+ READ_ONLY=false
49
+ ```
50
+
51
+ ## 🖥️ Utilisation
52
+
53
+ ### Mode Développement
54
+ Pour lancer le serveur directement avec `ts-node` :
55
+ ```bash
56
+ npm start
57
+ ```
58
+
59
+ ### Build et Production
60
+ Pour compiler en JavaScript :
61
+ ```bash
62
+ npm run build
63
+ node dist/index.js
64
+ ```
65
+
66
+ ### Intégration dans Cursor
67
+ Pour utiliser ce serveur dans Cursor :
68
+ 1. Allez dans les paramètres de Cursor (Cursor Settings) > MCP.
69
+ 2. Ajoutez un nouveau serveur MCP :
70
+ - **Name** : GitHub Controlled
71
+ - **Type** : `command`
72
+ - **Command** : `node "C:/chemin/vers/githubmcp/node_modules/ts-node/dist/bin.js" "C:/chemin/vers/githubmcp/src/index.ts"`
73
+ - **Environment Variables** : (Vous pouvez aussi les définir ici au lieu du fichier .env)
74
+
75
+ ### Intégration dans Claude Desktop
76
+ Ajoutez la configuration suivante dans votre fichier `claude_desktop_config.json` :
77
+
78
+ ```json
79
+ {
80
+ "mcpServers": {
81
+ "github-controlled": {
82
+ "command": "node",
83
+ "args": [
84
+ "C:/chemin/vers/githubmcp/node_modules/ts-node/dist/bin.js",
85
+ "C:/chemin/vers/githubmcp/src/index.ts"
86
+ ],
87
+ "env": {
88
+ "GITHUB_TOKEN": "votre_token",
89
+ "ALLOWED_REPOS": "org/repo",
90
+ "ALLOWED_BRANCHES": "mcp-*",
91
+ "READ_ONLY": "false"
92
+ }
93
+ }
94
+ }
95
+ }
96
+ ```
97
+
98
+ ## 🧪 Debugging
99
+ Vous pouvez utiliser l'inspecteur MCP pour tester le serveur localement :
100
+ ```bash
101
+ npx @modelcontextprotocol/inspector node dist/index.js
102
+ ```
103
+
104
+ ## 📄 Licence
105
+ ISC
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ import { Octokit } from "octokit";
6
+ import * as dotenv from "dotenv";
7
+ import { execSync } from "child_process";
8
+ // MCP servers must not log to stdout as it's used for the protocol.
9
+ // Some libraries might log to stdout on initialization.
10
+ // We redirect all console.log to console.error to avoid polluting stdout.
11
+ console.log = console.error;
12
+ dotenv.config();
13
+ const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
14
+ const TARGET_BRANCH = process.env.TARGET_BRANCH;
15
+ const BASE_BRANCH = process.env.BASE_BRANCH || "main";
16
+ const TARGET_REPO = process.env.TARGET_REPO;
17
+ const READ_ONLY = process.env.READ_ONLY === "true";
18
+ if (!GITHUB_TOKEN) {
19
+ console.error("GITHUB_TOKEN environment variable is required");
20
+ process.exit(1);
21
+ }
22
+ const octokit = new Octokit({ auth: GITHUB_TOKEN });
23
+ const server = new Server({
24
+ name: "restricted-github-mcp",
25
+ version: "1.0.0",
26
+ }, {
27
+ capabilities: {
28
+ tools: {},
29
+ },
30
+ });
31
+ const TOOLS = [
32
+ {
33
+ name: "push",
34
+ description: "Automated push: adds all local changes (including untracked), commits with a message, and pushes to the specific branch defined in TARGET_BRANCH",
35
+ inputSchema: {
36
+ type: "object",
37
+ properties: {
38
+ message: { type: "string", description: "The commit message" },
39
+ },
40
+ required: ["message"],
41
+ },
42
+ },
43
+ {
44
+ name: "pull_request",
45
+ description: "Create a pull request from the TARGET_BRANCH to the BASE_BRANCH",
46
+ inputSchema: {
47
+ type: "object",
48
+ properties: {
49
+ title: { type: "string", description: "The title of the pull request" },
50
+ body: { type: "string", description: "The body/description of the pull request" },
51
+ },
52
+ required: ["title"],
53
+ },
54
+ },
55
+ ];
56
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
57
+ tools: TOOLS,
58
+ }));
59
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
60
+ const { name, arguments: args } = request.params;
61
+ try {
62
+ switch (name) {
63
+ case "push": {
64
+ if (READ_ONLY)
65
+ throw new Error("Server is in read-only mode");
66
+ const { message } = args;
67
+ if (!TARGET_BRANCH) {
68
+ throw new Error("TARGET_BRANCH environment variable is not defined");
69
+ }
70
+ try {
71
+ // 1. Add all changes (including untracked)
72
+ execSync("git add .");
73
+ // 2. Commit
74
+ try {
75
+ execSync(`git commit -m "${message}"`);
76
+ }
77
+ catch (e) {
78
+ // Check if there was nothing to commit
79
+ const status = execSync("git status --porcelain").toString();
80
+ if (status.length === 0) {
81
+ return {
82
+ content: [{ type: "text", text: "Nothing to commit, working tree clean." }],
83
+ };
84
+ }
85
+ throw e;
86
+ }
87
+ // 3. Push to target branch
88
+ // If TARGET_REPO is defined (e.g. "user/repo"), we push to that remote
89
+ // Otherwise we push to 'origin'
90
+ const remote = TARGET_REPO && GITHUB_TOKEN
91
+ ? `https://x-access-token:${GITHUB_TOKEN}@github.com/${TARGET_REPO}.git`
92
+ : "origin";
93
+ execSync(`git push ${remote} HEAD:${TARGET_BRANCH}`);
94
+ return {
95
+ content: [{ type: "text", text: `Successfully committed and pushed all changes to branch ${TARGET_BRANCH}` }],
96
+ };
97
+ }
98
+ catch (error) {
99
+ throw new Error(`Git operation failed: ${error.message}`);
100
+ }
101
+ }
102
+ case "pull_request": {
103
+ if (READ_ONLY)
104
+ throw new Error("Server is in read-only mode");
105
+ const { title, body } = args;
106
+ if (!TARGET_REPO || !TARGET_REPO.includes("/")) {
107
+ throw new Error("TARGET_REPO must be defined as 'owner/repo'");
108
+ }
109
+ if (!TARGET_BRANCH) {
110
+ throw new Error("TARGET_BRANCH is not defined");
111
+ }
112
+ const [owner, repo] = TARGET_REPO.split("/");
113
+ if (!owner || !repo) {
114
+ throw new Error("Invalid TARGET_REPO format. Expected 'owner/repo'");
115
+ }
116
+ try {
117
+ const response = await octokit.rest.pulls.create({
118
+ owner,
119
+ repo,
120
+ title,
121
+ body,
122
+ head: TARGET_BRANCH,
123
+ base: BASE_BRANCH,
124
+ });
125
+ return {
126
+ content: [{ type: "text", text: `Pull request created successfully: ${response.data.html_url}` }],
127
+ };
128
+ }
129
+ catch (error) {
130
+ throw new Error(`Failed to create pull request: ${error.message}`);
131
+ }
132
+ }
133
+ default:
134
+ throw new Error(`Unknown tool: ${name}`);
135
+ }
136
+ }
137
+ catch (error) {
138
+ return {
139
+ content: [{ type: "text", text: `Error: ${error.message}` }],
140
+ isError: true,
141
+ };
142
+ }
143
+ });
144
+ async function main() {
145
+ const transport = new StdioServerTransport();
146
+ await server.connect(transport);
147
+ console.error("GitHub MCP Server running on stdio");
148
+ }
149
+ main().catch((error) => {
150
+ console.error("Fatal error in main():", error);
151
+ process.exit(1);
152
+ });
153
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "restricted-github-mcp",
3
+ "version": "1.0.0",
4
+ "main": "index.js",
5
+ "type": "module",
6
+ "files": [
7
+ "dist"
8
+ ],
9
+ "bin": {
10
+ "restricted-github-mcp": "./dist/index.js"
11
+ },
12
+ "scripts": {
13
+ "start": "tsx src/index.ts",
14
+ "dev": "tsx src/index.ts",
15
+ "build": "tsc",
16
+ "test": "echo \"Error: no test specified\" && exit 1",
17
+ "inspect": "mcp-inspector node dist/index.js",
18
+ "inspect:dev": "mcp-inspector --config mcp-config.json",
19
+ "inspect:no-auth": "mcp-inspector -e DANGEROUSLY_OMIT_AUTH=true --config mcp-config.json"
20
+ },
21
+ "keywords": [],
22
+ "author": "",
23
+ "license": "ISC",
24
+ "description": "Un serveur MCP GitHub contrôlé et sécurisé pour les agents IA.",
25
+ "dependencies": {
26
+ "@modelcontextprotocol/sdk": "^1.25.3",
27
+ "dotenv": "^17.2.3",
28
+ "octokit": "^5.0.5"
29
+ },
30
+ "devDependencies": {
31
+ "@modelcontextprotocol/inspector": "^0.19.0",
32
+ "@types/node": "^25.0.10",
33
+ "tsx": "^4.21.0",
34
+ "typescript": "^5.9.3"
35
+ }
36
+ }