@cyanheads/git-mcp-server 2.2.2 → 2.2.4

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 (38) hide show
  1. package/README.md +69 -122
  2. package/dist/config/index.js +248 -53
  3. package/dist/mcp-server/resources/gitWorkingDir/index.js +5 -0
  4. package/dist/mcp-server/resources/gitWorkingDir/logic.js +17 -0
  5. package/dist/mcp-server/resources/gitWorkingDir/registration.js +64 -0
  6. package/dist/mcp-server/server.js +11 -6
  7. package/dist/mcp-server/tools/gitCherryPick/logic.js +39 -13
  8. package/dist/mcp-server/tools/gitCommit/logic.js +1 -1
  9. package/dist/mcp-server/tools/gitMerge/logic.js +38 -13
  10. package/dist/mcp-server/tools/gitTag/logic.js +38 -19
  11. package/dist/mcp-server/transports/auth/authFactory.js +41 -0
  12. package/dist/mcp-server/transports/auth/authMiddleware.js +57 -0
  13. package/dist/mcp-server/transports/auth/index.js +6 -4
  14. package/dist/mcp-server/transports/auth/lib/authTypes.js +8 -0
  15. package/dist/mcp-server/transports/auth/{core → lib}/authUtils.js +21 -14
  16. package/dist/mcp-server/transports/auth/strategies/authStrategy.js +1 -0
  17. package/dist/mcp-server/transports/auth/strategies/jwtStrategy.js +113 -0
  18. package/dist/mcp-server/transports/auth/strategies/oauthStrategy.js +102 -0
  19. package/dist/mcp-server/transports/core/baseTransportManager.js +19 -0
  20. package/dist/mcp-server/transports/core/honoNodeBridge.js +51 -0
  21. package/dist/mcp-server/transports/core/statefulTransportManager.js +234 -0
  22. package/dist/mcp-server/transports/core/statelessTransportManager.js +92 -0
  23. package/dist/mcp-server/transports/core/transportTypes.js +5 -0
  24. package/dist/mcp-server/transports/{httpErrorHandler.js → http/httpErrorHandler.js} +33 -8
  25. package/dist/mcp-server/transports/http/httpTransport.js +254 -0
  26. package/dist/mcp-server/transports/http/httpTypes.js +5 -0
  27. package/dist/mcp-server/transports/http/index.js +6 -0
  28. package/dist/mcp-server/transports/http/mcpTransportMiddleware.js +63 -0
  29. package/dist/mcp-server/transports/stdio/index.js +5 -0
  30. package/dist/mcp-server/transports/{stdioTransport.js → stdio/stdioTransport.js} +10 -5
  31. package/dist/types-global/errors.js +75 -19
  32. package/dist/utils/internal/errorHandler.js +11 -13
  33. package/package.json +18 -7
  34. package/dist/mcp-server/transports/auth/core/authTypes.js +0 -5
  35. package/dist/mcp-server/transports/auth/strategies/jwt/jwtMiddleware.js +0 -149
  36. package/dist/mcp-server/transports/auth/strategies/oauth/oauthMiddleware.js +0 -127
  37. package/dist/mcp-server/transports/httpTransport.js +0 -207
  38. /package/dist/mcp-server/transports/auth/{core → lib}/authContext.js +0 -0
package/README.md CHANGED
@@ -1,18 +1,31 @@
1
- # Git MCP Server
1
+ <div align="center">
2
2
 
3
- [![TypeScript](https://img.shields.io/badge/TypeScript-^5.8.3-blue.svg)](https://www.typescriptlang.org/)
4
- [![Model Context Protocol](https://img.shields.io/badge/MCP%20SDK-^1.15.1-green.svg)](https://modelcontextprotocol.io/)
5
- [![Version](https://img.shields.io/badge/Version-2.2.0-blue.svg)](./CHANGELOG.md)
6
- [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
7
- [![Status](https://img.shields.io/badge/Status-Stable-green.svg)](https://github.com/cyanheads/git-mcp-server/issues)
8
- [![GitHub](https://img.shields.io/github/stars/cyanheads/git-mcp-server?style=social)](https://github.com/cyanheads/git-mcp-server)
3
+ # @cyanheads/git-mcp-server
9
4
 
10
5
  **Empower your AI agents with comprehensive, secure, and programmatic control over Git repositories!**
11
6
 
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-^5.8.3-blue?style=flat-square)](https://www.typescriptlang.org/)
8
+ [![Model Context Protocol SDK](https://img.shields.io/badge/MCP%20SDK-^1.17.0-green?style=flat-square)](https://github.com/modelcontextprotocol/typescript-sdk)
9
+ [![MCP Spec Version](https://img.shields.io/badge/MCP%20Spec-2025--06--18-lightgrey?style=flat-square)](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-06-18/changelog.mdx)
10
+ [![Version](https://img.shields.io/badge/Version-2.2.4-blue?style=flat-square)](./CHANGELOG.md)
11
+ [![Coverage](https://img.shields.io/badge/Coverage-0.0%25-red?style=flat-square)](./vitest.config.ts)
12
+ [![License](https://img.shields.io/badge/License-Apache%202.0-blue?style=flat-square)](https://opensource.org/licenses/Apache-2.0)
13
+ [![Status](https://img.shields.io/badge/Status-Stable-green?style=flat-square)](https://github.com/cyanheads/git-mcp-server/issues)
14
+ [![GitHub](https://img.shields.io/github/stars/cyanheads/git-mcp-server?style=social)](https://github.com/cyanheads/git-mcp-server)
15
+
16
+ </div>
17
+
12
18
  An MCP (Model Context Protocol) server providing a robust, LLM-friendly interface to the standard `git` command-line tool. Enables LLMs and AI agents to perform a wide range of Git operations like clone, commit, push, pull, branch, diff, log, status, and more via the MCP standard.
13
19
 
14
20
  Built on the [`cyanheads/mcp-ts-template`](https://github.com/cyanheads/mcp-ts-template), this server follows a modular architecture with robust error handling, logging, and security features.
15
21
 
22
+ ## 🤔 Why Use This Server?
23
+
24
+ - **Automate Git Workflows**: Enable AI agents to programmatically clone, commit, push, and manage branches.
25
+ - **Gain Repository Insights**: Allow tools to check status, view logs, and diff changes without direct shell access.
26
+ - **Integrate Git into AI-driven Development**: Let LLMs manage version control as part of their coding tasks.
27
+ - **Production-Ready Foundation**: Inherits logging, error handling, and security from the template.
28
+
16
29
  ## 🚀 Core Capabilities: Git Tools 🛠️
17
30
 
18
31
  This server equips your AI with a comprehensive suite of tools to interact with Git repositories:
@@ -104,35 +117,41 @@ Add the following to your MCP client's configuration file (e.g., `cline_mcp_sett
104
117
  #### Install via npm
105
118
 
106
119
  ```bash
107
- npm install @cyanheads/git-mcp-server
120
+ npm run build
121
+ # Or use 'npm run rebuild' for a clean install
108
122
  ```
109
123
 
110
- #### Alternatively Install from Source (recommended for development)
124
+ ### 3. Running the Server
111
125
 
112
- 1. Clone the repository:
126
+ - **Via Stdio (Default):**
127
+ ```bash
128
+ npm run start:server
129
+ ```
130
+ - **Via Streamable HTTP:**
131
+ ```bash
132
+ npm run start:server:http
133
+ ```
113
134
 
114
- ```bash
115
- git clone https://github.com/cyanheads/git-mcp-server.git
116
- cd git-mcp-server
117
- ```
135
+ ### 4. Running Tests
118
136
 
119
- 2. Install dependencies:
137
+ This server uses [Vitest](https://vitest.dev/) for testing.
120
138
 
121
- ```bash
122
- npm install
123
- ```
139
+ - **Run all tests once:**
140
+ ```bash
141
+ npm test
142
+ ```
143
+ - **Run tests in watch mode:**
144
+ ```bash
145
+ npm run test:watch
146
+ ```
147
+ - **Run tests and generate a coverage report:**
148
+ ```bash
149
+ npm run test:coverage
150
+ ```
124
151
 
125
- 3. Build the project:
126
- ```bash
127
- npm run build
128
- # or npm run rebuild
129
- ```
152
+ ## ⚙️ Configuration
130
153
 
131
- ## Configuration
132
-
133
- ### Environment Variables
134
-
135
- Configure the server using environment variables. These environmental variables are set within your MCP client config/settings (e.g. `claude_desktop_config.json` for Claude Desktop)
154
+ Configure the server using these environment variables (or a `.env` file):
136
155
 
137
156
  | Variable | Description | Default |
138
157
  | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
@@ -147,111 +166,39 @@ Configure the server using environment variables. These environmental variables
147
166
  | `OAUTH_ISSUER_URL` | OIDC issuer URL for OAuth validation (if `MCP_AUTH_MODE=oauth`). | `''` |
148
167
  | `OAUTH_AUDIENCE` | Audience claim for OAuth validation (if `MCP_AUTH_MODE=oauth`). | `''` |
149
168
 
150
- ## Project Structure
151
-
152
- The codebase follows a modular structure within the `src/` directory:
153
-
154
- ```
155
- src/
156
- ├── index.ts # Entry point: Initializes and starts the server
157
- ├── config/ # Configuration loading (env vars, package info)
158
- │ └── index.ts
159
- ├── mcp-server/ # Core MCP server logic and capability registration
160
- │ ├── server.ts # Server setup, capability registration
161
- │ ├── transports/ # Transport handling (stdio, http)
162
- │ ├── resources/ # MCP Resource implementations (currently none)
163
- │ └── tools/ # MCP Tool implementations (subdirs per tool)
164
- ├── types-global/ # Shared TypeScript type definitions
165
- └── utils/ # Common utility functions (logger, error handler, etc.)
166
- ```
167
-
168
- For a detailed file tree, run `npm run tree` or see [docs/tree.md](docs/tree.md).
169
-
170
- ## Tools
171
-
172
- The Git MCP Server provides a suite of tools for interacting with Git repositories, callable via the Model Context Protocol.
169
+ ## 🏗️ Project Structure
173
170
 
174
- | Tool Name | Description | Key Arguments |
175
- | :------------------------ | :--------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ |
176
- | `git_add` | Stages specified files or patterns. | `path?`, `files?` |
177
- | `git_branch` | Manages branches (list, create, delete, rename, show current). | `path?`, `mode`, `branchName?`, `newBranchName?`, `startPoint?`, `force?`, `all?`, `remote?` |
178
- | `git_checkout` | Switches branches or restores working tree files. | `path?`, `branchOrPath`, `newBranch?`, `force?` |
179
- | `git_cherry_pick` | Applies changes introduced by existing commits. | `path?`, `commitRef`, `mainline?`, `strategy?`, `noCommit?`, `signoff?` |
180
- | `git_clean` | Removes untracked files. **Requires `force: true`**. | `path?`, `force`, `dryRun?`, `directories?`, `ignored?` |
181
- | `git_clear_working_dir` | Clears the session-specific working directory. | (none) |
182
- | `git_clone` | Clones a repository into a specified absolute path. | `repositoryUrl`, `targetPath`, `branch?`, `depth?`, `quiet?` |
183
- | `git_commit` | Commits staged changes. Supports author override, signing control. | `path?`, `message`, `author?`, `allowEmpty?`, `amend?`, `forceUnsignedOnFailure?` |
184
- | `git_diff` | Shows changes between commits, working tree, etc. | `path?`, `commit1?`, `commit2?`, `staged?`, `file?`, `includeUntracked?` |
185
- | `git_fetch` | Downloads objects and refs from other repositories. | `path?`, `remote?`, `prune?`, `tags?`, `all?` |
186
- | `git_init` | Initializes a new Git repository at the specified absolute path. Defaults to 'main' for initial branch. | `path`, `initialBranch?`, `bare?`, `quiet?` |
187
- | `git_log` | Shows commit logs. | `path?`, `maxCount?`, `author?`, `since?`, `until?`, `branchOrFile?` |
188
- | `git_merge` | Merges the specified branch into the current branch. | `path?`, `branch`, `commitMessage?`, `noFf?`, `squash?`, `abort?` |
189
- | `git_pull` | Fetches from and integrates with another repository or local branch. | `path?`, `remote?`, `branch?`, `rebase?`, `ffOnly?` |
190
- | `git_push` | Updates remote refs using local refs. | `path?`, `remote?`, `branch?`, `remoteBranch?`, `force?`, `forceWithLease?`, `setUpstream?`, `tags?`, `delete?` |
191
- | `git_rebase` | Reapplies commits on top of another base tip. | `path?`, `mode?`, `upstream?`, `branch?`, `interactive?`, `strategy?`, `strategyOption?`, `onto?` |
192
- | `git_remote` | Manages remote repositories (list, add, remove, show). | `path?`, `mode`, `name?`, `url?` |
193
- | `git_reset` | Resets current HEAD to a specified state. Supports soft, mixed, hard modes. **USE 'hard' WITH CAUTION**. | `path?`, `mode?`, `commit?` |
194
- | `git_set_working_dir` | Sets the default working directory. Can optionally initialize repo if not present. Requires absolute path. | `path`, `validateGitRepo?`, `initializeIfNotPresent?` |
195
- | `git_show` | Shows information about Git objects (commits, tags, etc.). | `path?`, `ref`, `filePath?` |
196
- | `git_stash` | Manages stashed changes (list, apply, pop, drop, save). | `path?`, `mode`, `stashRef?`, `message?` |
197
- | `git_status` | Gets repository status (branch, staged, modified, untracked files). | `path?` |
198
- | `git_tag` | Manages tags (list, create annotated/lightweight, delete). | `path?`, `mode`, `tagName?`, `message?`, `commitRef?`, `annotate?` |
199
- | `git_worktree` | Manages Git worktrees (list, add, remove, move, prune). | `path?`, `mode`, `worktreePath?`, `commitish?`, `newBranch?`, `force?`, `detach?`, `newPath?`, `verbose?`, `dryRun?`, `expire?` |
200
- | `git_wrapup_instructions` | Provides a standard Git wrap-up workflow. | `acknowledgement`, `updateAgentMetaFiles?` |
171
+ - **`src/mcp-server/`**: Contains the core MCP server, tools, resources, and transport handlers.
172
+ - **`src/config/`**: Handles loading and validation of environment variables.
173
+ - **`src/types-global/`**: Defines shared TypeScript interfaces and type definitions.
174
+ - **`src/utils/`**: Core utilities (logging, error handling, security, etc.).
175
+ - **`src/index.ts`**: The main entry point that initializes and starts the server.
201
176
 
202
- _Note: The `path` parameter for most tools defaults to the session's working directory if set via `git_set_working_dir`._
177
+ **Explore the full structure yourself:**
203
178
 
204
- ## Resources
205
-
206
- **MCP Resources are not implemented in this version (v2.2.0).**
207
-
208
- This version focuses on the refactored Git tools implementation based on the latest `mcp-ts-template` and MCP SDK v1.15.1. Resource capabilities, previously available, have been temporarily removed during this major update.
209
-
210
- If you require MCP Resource access (e.g., for reading file content directly via the server), please use the stable **[v1.2.4 release](https://github.com/cyanheads/git-mcp-server/releases/tag/v1.2.4)**.
211
-
212
- Future development may reintroduce resource capabilities in a subsequent release.
213
-
214
- ## Development
215
-
216
- ### Build and Test
179
+ See the current file tree in [docs/tree.md](docs/tree.md) or generate it dynamically:
217
180
 
218
181
  ```bash
219
- # Build the project (compile TS to JS in dist/ and make executable)
220
- npm run build
221
-
222
- # Test the server locally using the MCP inspector tool (stdio transport)
223
- npm run inspector
224
-
225
- # Test the server locally using the MCP inspector tool (http transport)
226
- npm run inspector:http
227
-
228
- # Clean build artifacts
229
- npm run clean
230
-
231
- # Generate a file tree representation for documentation
232
182
  npm run tree
183
+ ```
233
184
 
234
- # Clean build artifacts and then rebuild the project
235
- npm run rebuild
185
+ ## 📦 Resources
236
186
 
237
- # Format code with Prettier
238
- npm run format
187
+ In addition to tools, the server provides resources that offer contextual information about the Git environment.
239
188
 
240
- # Start the server using stdio (default)
241
- npm start
242
- # Or explicitly:
243
- npm run start:stdio
189
+ | Resource URI | Description |
190
+ | :------------------------ | :--------------------------------------------------------------------------------------------------------- |
191
+ | `git://working-directory` | Returns the currently configured working directory for the session as a JSON object. Shows `NOT_SET` if unset. |
244
192
 
245
- # Start the server using HTTP transport
246
- npm run start:http
247
- ```
193
+ ## 🧩 Extending the System
248
194
 
249
- ## License
195
+ The canonical pattern for adding new tools is defined in the [.clinerules](.clinerules) file. It mandates a strict separation of concerns:
250
196
 
251
- This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
197
+ 1. **`logic.ts`**: Contains the pure business logic, Zod schemas, and type definitions. This file throws structured errors on failure.
198
+ 2. **`registration.ts`**: Acts as the "handler." It registers the tool with the server, wraps the logic call in a `try...catch` block, and formats the final success or error response.
252
199
 
253
- ---
200
+ This "Logic Throws, Handler Catches" pattern ensures that core logic remains pure and testable, while the registration layer handles all side effects and response formatting.
254
201
 
255
- <div align="center">
256
- Built with the <a href="https://modelcontextprotocol.io/">Model Context Protocol</a>
257
- </div>
202
+ ## 📜 License
203
+
204
+ This project is licensed under the Apache License 2.0. See the [LICENSE](LICENSE) file for details.
@@ -1,76 +1,271 @@
1
+ /**
2
+ * @fileoverview Loads, validates, and exports application configuration.
3
+ * This module centralizes configuration management, sourcing values from
4
+ * environment variables and `package.json`. It uses Zod for schema validation
5
+ * to ensure type safety and correctness of configuration parameters.
6
+ *
7
+ * Key responsibilities:
8
+ * - Load environment variables from a `.env` file.
9
+ * - Read `package.json` for default server name and version.
10
+ * - Define a Zod schema for all expected environment variables.
11
+ * - Validate environment variables against the schema.
12
+ * - Construct and export a comprehensive `config` object.
13
+ * - Export individual configuration values like `logLevel` and `environment` for convenience.
14
+ *
15
+ * @module src/config/index
16
+ */
1
17
  import dotenv from "dotenv";
2
- import { readFileSync } from "fs";
3
- import { dirname, join } from "path";
18
+ import { existsSync, mkdirSync, readFileSync, statSync } from "fs";
19
+ import path, { dirname, join } from "path";
4
20
  import { fileURLToPath } from "url";
5
- // Removed logger import to break circular dependency
6
- // Suppress dotenv debug output which can interfere with stdio transport
7
- dotenv.config({ debug: false }); // Load environment variables from .env file
8
- // Determine the directory name of the current module
9
- const __dirname = dirname(fileURLToPath(import.meta.url));
10
- // Construct the path to package.json relative to the current file
11
- const pkgPath = join(__dirname, "../../package.json");
12
- // Default package information in case package.json is unreadable
13
- let pkg = { name: "git-mcp-server-SOMETHINGBROKE", version: "0.0.0" };
21
+ import { z } from "zod";
22
+ dotenv.config();
23
+ // --- Determine Project Root ---
24
+ /**
25
+ * Finds the project root directory by searching upwards for package.json.
26
+ * @param startDir The directory to start searching from.
27
+ * @returns The absolute path to the project root, or throws an error if not found.
28
+ */
29
+ const findProjectRoot = (startDir) => {
30
+ let currentDir = startDir;
31
+ while (true) {
32
+ const packageJsonPath = join(currentDir, "package.json");
33
+ if (existsSync(packageJsonPath)) {
34
+ return currentDir;
35
+ }
36
+ const parentDir = dirname(currentDir);
37
+ if (parentDir === currentDir) {
38
+ // Reached the root of the filesystem without finding package.json
39
+ throw new Error(`Could not find project root (package.json) starting from ${startDir}`);
40
+ }
41
+ currentDir = parentDir;
42
+ }
43
+ };
44
+ let projectRoot;
45
+ try {
46
+ // For ESM, __dirname is not available directly.
47
+ // import.meta.url gives the URL of the current module.
48
+ const currentModuleDir = dirname(fileURLToPath(import.meta.url));
49
+ projectRoot = findProjectRoot(currentModuleDir);
50
+ }
51
+ catch (error) {
52
+ const errorMessage = error instanceof Error ? error.message : String(error);
53
+ console.error(`FATAL: Error determining project root: ${errorMessage}`);
54
+ // Fallback to process.cwd() if project root cannot be determined.
55
+ // This might happen in unusual execution environments.
56
+ projectRoot = process.cwd();
57
+ console.warn(`Warning: Using process.cwd() (${projectRoot}) as fallback project root.`);
58
+ }
59
+ // --- End Determine Project Root ---
60
+ const pkgPath = join(projectRoot, "package.json"); // Use determined projectRoot
61
+ let pkg = { name: "git-mcp-server", version: "0.0.0" };
14
62
  try {
15
- // Read and parse package.json to get server name and version
16
63
  pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
17
64
  }
18
65
  catch (error) {
19
- // Silently use default pkg info if reading fails. Error will be logged later if needed.
66
+ if (process.stdout.isTTY) {
67
+ console.error("Warning: Could not read package.json for default config values. Using hardcoded defaults.", error);
68
+ }
69
+ }
70
+ /**
71
+ * Zod schema for validating environment variables.
72
+ * Provides type safety, validation, defaults, and clear error messages.
73
+ * @private
74
+ */
75
+ const EnvSchema = z.object({
76
+ /** Optional. The desired name for the MCP server. Defaults to `package.json` name. */
77
+ MCP_SERVER_NAME: z.string().optional(),
78
+ /** Optional. The version of the MCP server. Defaults to `package.json` version. */
79
+ MCP_SERVER_VERSION: z.string().optional(),
80
+ /** Minimum logging level. See `McpLogLevel` in logger utility. Default: "info". */
81
+ MCP_LOG_LEVEL: z.string().default("info"),
82
+ /** Directory for log files. Defaults to "logs" in project root. */
83
+ LOGS_DIR: z.string().default(path.join(projectRoot, "logs")),
84
+ /** Runtime environment (e.g., "development", "production"). Default: "development". */
85
+ NODE_ENV: z.string().default("development"),
86
+ /** MCP communication transport ("stdio" or "http"). Default: "stdio". */
87
+ MCP_TRANSPORT_TYPE: z.enum(["stdio", "http"]).default("stdio"),
88
+ /** MCP session mode ('stateless', 'stateful', 'auto'). Default: 'auto'. */
89
+ MCP_SESSION_MODE: z.enum(["stateless", "stateful", "auto"]).default("auto"),
90
+ /** HTTP server port (if MCP_TRANSPORT_TYPE is "http"). Default: 3010. */
91
+ MCP_HTTP_PORT: z.coerce.number().int().positive().default(3010),
92
+ /** HTTP server host (if MCP_TRANSPORT_TYPE is "http"). Default: "127.0.0.1". */
93
+ MCP_HTTP_HOST: z.string().default("127.0.0.1"),
94
+ /** The endpoint path for the MCP server. Default: "/mcp". */
95
+ MCP_HTTP_ENDPOINT_PATH: z.string().default("/mcp"),
96
+ /** Max retries for binding to a port if the initial one is in use. Default: 15. */
97
+ MCP_HTTP_MAX_PORT_RETRIES: z.coerce.number().int().nonnegative().default(15),
98
+ /** Delay in ms between port binding retries. Default: 50. */
99
+ MCP_HTTP_PORT_RETRY_DELAY_MS: z.coerce
100
+ .number()
101
+ .int()
102
+ .nonnegative()
103
+ .default(50),
104
+ /** Timeout in ms for considering a stateful session stale and eligible for cleanup. Default: 1800000 (30 minutes). */
105
+ MCP_STATEFUL_SESSION_STALE_TIMEOUT_MS: z.coerce
106
+ .number()
107
+ .int()
108
+ .positive()
109
+ .default(1_800_000),
110
+ /** Optional. Comma-separated allowed origins for CORS (HTTP transport). */
111
+ MCP_ALLOWED_ORIGINS: z.string().optional(),
112
+ /** Optional. Secret key (min 32 chars) for auth tokens (HTTP transport). CRITICAL for production. */
113
+ MCP_AUTH_SECRET_KEY: z
114
+ .string()
115
+ .min(32, "MCP_AUTH_SECRET_KEY must be at least 32 characters long for security reasons.")
116
+ .optional(),
117
+ /** The authentication mode to use. 'jwt' for internal simple JWTs, 'oauth' for OAuth 2.1, or 'none'. Default: 'none'. */
118
+ MCP_AUTH_MODE: z.enum(["jwt", "oauth", "none"]).default("none"),
119
+ /** The expected issuer URL for OAuth 2.1 access tokens. CRITICAL for validation. */
120
+ OAUTH_ISSUER_URL: z.string().url().optional(),
121
+ /** The JWKS (JSON Web Key Set) URI for the OAuth 2.1 provider. If not provided, it's often discoverable from the issuer URL. */
122
+ OAUTH_JWKS_URI: z.string().url().optional(),
123
+ /** The audience claim for the OAuth 2.1 access tokens. This server will reject tokens not intended for it. */
124
+ OAUTH_AUDIENCE: z.string().optional(),
125
+ /** Optional. Client ID to use in development mode for JWT strategy. Default: "dev-client-id". */
126
+ DEV_MCP_CLIENT_ID: z.string().optional(),
127
+ /** Optional. Comma-separated scopes for development mode JWT strategy. Default: "dev-scope". */
128
+ DEV_MCP_SCOPES: z.string().optional(),
129
+ /** Flag to enable GPG signing for commits made by the git_commit tool. */
130
+ GIT_SIGN_COMMITS: z.string().transform((val) => val === "true").optional(),
131
+ });
132
+ const parsedEnv = EnvSchema.safeParse(process.env);
133
+ if (!parsedEnv.success) {
134
+ if (process.stdout.isTTY) {
135
+ console.error("❌ Invalid environment variables found:", parsedEnv.error.flatten().fieldErrors);
136
+ }
137
+ // Consider throwing an error in production for critical misconfigurations.
138
+ }
139
+ const env = parsedEnv.success ? parsedEnv.data : EnvSchema.parse({});
140
+ // --- Directory Ensurance Function ---
141
+ const ensureDirectory = (dirPath, rootDir, dirName) => {
142
+ const resolvedDirPath = path.isAbsolute(dirPath)
143
+ ? dirPath
144
+ : path.resolve(rootDir, dirPath);
145
+ if (!resolvedDirPath.startsWith(rootDir + path.sep) &&
146
+ resolvedDirPath !== rootDir) {
147
+ if (process.stdout.isTTY) {
148
+ console.error(`Error: ${dirName} path "${dirPath}" resolves to "${resolvedDirPath}", which is outside the project boundary "${rootDir}".`);
149
+ }
150
+ return null;
151
+ }
152
+ if (!existsSync(resolvedDirPath)) {
153
+ try {
154
+ mkdirSync(resolvedDirPath, { recursive: true });
155
+ if (process.stdout.isTTY) {
156
+ console.log(`Created ${dirName} directory: ${resolvedDirPath}`);
157
+ }
158
+ }
159
+ catch (err) {
160
+ const errorMessage = err instanceof Error ? err.message : String(err);
161
+ if (process.stdout.isTTY) {
162
+ console.error(`Error creating ${dirName} directory at ${resolvedDirPath}: ${errorMessage}`);
163
+ }
164
+ return null;
165
+ }
166
+ }
167
+ else {
168
+ try {
169
+ const stats = statSync(resolvedDirPath);
170
+ if (!stats.isDirectory()) {
171
+ if (process.stdout.isTTY) {
172
+ console.error(`Error: ${dirName} path ${resolvedDirPath} exists but is not a directory.`);
173
+ }
174
+ return null;
175
+ }
176
+ }
177
+ catch (statError) {
178
+ if (process.stdout.isTTY) {
179
+ const statErrorMessage = statError instanceof Error ? statError.message : String(statError);
180
+ console.error(`Error accessing ${dirName} path ${resolvedDirPath}: ${statErrorMessage}`);
181
+ }
182
+ return null;
183
+ }
184
+ }
185
+ return resolvedDirPath;
186
+ };
187
+ // --- End Directory Ensurance Function ---
188
+ // --- Logs Directory Handling ---
189
+ let validatedLogsPath = ensureDirectory(env.LOGS_DIR, projectRoot, "logs");
190
+ if (!validatedLogsPath) {
191
+ if (process.stdout.isTTY) {
192
+ console.warn(`Warning: Custom logs directory ('${env.LOGS_DIR}') is invalid or outside the project boundary. Falling back to default.`);
193
+ }
194
+ const defaultLogsDir = path.join(projectRoot, "logs");
195
+ validatedLogsPath = ensureDirectory(defaultLogsDir, projectRoot, "logs");
196
+ if (!validatedLogsPath) {
197
+ if (process.stdout.isTTY) {
198
+ console.warn("Warning: Default logs directory could not be created. File logging will be disabled.");
199
+ }
200
+ }
20
201
  }
202
+ // --- End Logs Directory Handling ---
21
203
  /**
22
204
  * Main application configuration object.
23
- * Aggregates settings from environment variables and package.json.
205
+ * Aggregates settings from validated environment variables and `package.json`.
24
206
  */
25
207
  export const config = {
26
- /** The name of the MCP server, derived from package.json. */
27
- mcpServerName: pkg.name,
28
- /** The version of the MCP server, derived from package.json. */
29
- mcpServerVersion: pkg.version,
30
- /** Logging level for the application (e.g., "debug", "info", "warning", "error"). Defaults to "info". */
31
- logLevel: process.env.MCP_LOG_LEVEL || "info", // Use MCP_LOG_LEVEL consistently
32
- /** The runtime environment (e.g., "development", "production"). Defaults to "development". */
33
- environment: process.env.NODE_ENV || "development",
34
- /** The communication transport type ('stdio' or 'http'). Defaults to 'stdio'. */
35
- mcpTransportType: process.env.MCP_TRANSPORT_TYPE || "stdio",
36
- /** Port for the HTTP transport. Defaults to 3000. */
37
- mcpHttpPort: parseInt(process.env.MCP_HTTP_PORT || "3010", 10),
38
- /** Host for the HTTP transport. Defaults to '127.0.0.1'. */
39
- mcpHttpHost: process.env.MCP_HTTP_HOST || "127.0.0.1",
40
- /** Allowed origins for HTTP transport (comma-separated). */
41
- mcpAllowedOrigins: process.env.MCP_ALLOWED_ORIGINS?.split(",") || [],
208
+ /** Information from package.json. */
209
+ pkg,
210
+ /** MCP server name. Env `MCP_SERVER_NAME` > `package.json` name > "git-mcp-server". */
211
+ mcpServerName: env.MCP_SERVER_NAME || pkg.name,
212
+ /** MCP server version. Env `MCP_SERVER_VERSION` > `package.json` version > "0.0.0". */
213
+ mcpServerVersion: env.MCP_SERVER_VERSION || pkg.version,
214
+ /** Logging level. From `MCP_LOG_LEVEL` env var. Default: "info". */
215
+ logLevel: env.MCP_LOG_LEVEL,
216
+ /** Absolute path to the logs directory. From `LOGS_DIR` env var. */
217
+ logsPath: validatedLogsPath,
218
+ /** Runtime environment. From `NODE_ENV` env var. Default: "development". */
219
+ environment: env.NODE_ENV,
220
+ /** MCP transport type ('stdio' or 'http'). From `MCP_TRANSPORT_TYPE` env var. Default: "stdio". */
221
+ mcpTransportType: env.MCP_TRANSPORT_TYPE,
222
+ /** MCP session mode ('stateless', 'stateful', 'auto'). From `MCP_SESSION_MODE` env var. Default: "auto". */
223
+ mcpSessionMode: env.MCP_SESSION_MODE,
224
+ /** HTTP server port (if http transport). From `MCP_HTTP_PORT` env var. Default: 3010. */
225
+ mcpHttpPort: env.MCP_HTTP_PORT,
226
+ /** HTTP server host (if http transport). From `MCP_HTTP_HOST` env var. Default: "127.0.0.1". */
227
+ mcpHttpHost: env.MCP_HTTP_HOST,
228
+ /** MCP endpoint path for HTTP transport. From `MCP_HTTP_ENDPOINT_PATH`. Default: "/mcp". */
229
+ mcpHttpEndpointPath: env.MCP_HTTP_ENDPOINT_PATH,
230
+ /** Max retries for port binding. From `MCP_HTTP_MAX_PORT_RETRIES`. Default: 15. */
231
+ mcpHttpMaxPortRetries: env.MCP_HTTP_MAX_PORT_RETRIES,
232
+ /** Delay between port binding retries. From `MCP_HTTP_PORT_RETRY_DELAY_MS`. Default: 50. */
233
+ mcpHttpPortRetryDelayMs: env.MCP_HTTP_PORT_RETRY_DELAY_MS,
234
+ /** Timeout for stale stateful sessions. From `MCP_STATEFUL_SESSION_STALE_TIMEOUT_MS`. Default: 1800000. */
235
+ mcpStatefulSessionStaleTimeoutMs: env.MCP_STATEFUL_SESSION_STALE_TIMEOUT_MS,
236
+ /** Array of allowed CORS origins (http transport). From `MCP_ALLOWED_ORIGINS` (comma-separated). */
237
+ mcpAllowedOrigins: env.MCP_ALLOWED_ORIGINS?.split(",")
238
+ .map((origin) => origin.trim())
239
+ .filter(Boolean),
240
+ /** Auth secret key (JWTs, http transport). From `MCP_AUTH_SECRET_KEY`. CRITICAL. */
241
+ mcpAuthSecretKey: env.MCP_AUTH_SECRET_KEY,
242
+ /** The authentication mode ('jwt' or 'oauth'). From `MCP_AUTH_MODE`. */
243
+ mcpAuthMode: env.MCP_AUTH_MODE,
244
+ /** OAuth 2.1 Issuer URL. From `OAUTH_ISSUER_URL`. */
245
+ oauthIssuerUrl: env.OAUTH_ISSUER_URL,
246
+ /** OAuth 2.1 JWKS URI. From `OAUTH_JWKS_URI`. */
247
+ oauthJwksUri: env.OAUTH_JWKS_URI,
248
+ /** OAuth 2.1 Audience. From `OAUTH_AUDIENCE`. */
249
+ oauthAudience: env.OAUTH_AUDIENCE,
250
+ /** Development mode client ID. From `DEV_MCP_CLIENT_ID`. */
251
+ devMcpClientId: env.DEV_MCP_CLIENT_ID,
252
+ /** Development mode scopes. From `DEV_MCP_SCOPES`. */
253
+ devMcpScopes: env.DEV_MCP_SCOPES?.split(",").map((s) => s.trim()),
42
254
  /** Flag to enable GPG signing for commits made by the git_commit tool. Requires server-side GPG setup. */
43
- gitSignCommits: process.env.GIT_SIGN_COMMITS === "true",
44
- /** The authentication mode ('jwt', 'oauth', or 'none'). Defaults to 'none'. */
45
- mcpAuthMode: process.env.MCP_AUTH_MODE || "none",
46
- /** Secret key for signing/verifying JWTs. Required if mcpAuthMode is 'jwt'. */
47
- mcpAuthSecretKey: process.env.MCP_AUTH_SECRET_KEY,
48
- /** The OIDC issuer URL for OAuth token validation. Required if mcpAuthMode is 'oauth'. */
49
- oauthIssuerUrl: process.env.OAUTH_ISSUER_URL,
50
- /** The audience claim for OAuth token validation. Required if mcpAuthMode is 'oauth'. */
51
- oauthAudience: process.env.OAUTH_AUDIENCE,
52
- /** The JWKS URI for fetching public keys for OAuth. Optional, can be derived from issuer URL. */
53
- oauthJwksUri: process.env.OAUTH_JWKS_URI,
255
+ gitSignCommits: env.GIT_SIGN_COMMITS,
54
256
  /** Security-related configurations. */
55
257
  security: {
56
- // Placeholder for security settings
57
- // Example: authRequired: process.env.AUTH_REQUIRED === 'true'
58
258
  /** Indicates if authentication is required for server operations. */
59
- authRequired: false,
259
+ authRequired: env.MCP_AUTH_MODE !== "none",
60
260
  },
61
- // Note: mcpClient configuration is now loaded separately from mcp-config.json
62
261
  };
63
262
  /**
64
- * The configured logging level for the application.
65
- * Exported separately for convenience (e.g., logger initialization).
66
- * @type {string}
263
+ * Configured logging level for the application.
264
+ * Exported for convenience.
67
265
  */
68
266
  export const logLevel = config.logLevel;
69
267
  /**
70
- * The configured runtime environment for the application.
71
- * Exported separately for convenience.
72
- * @type {string}
268
+ * Configured runtime environment ("development", "production", etc.).
269
+ * Exported for convenience.
73
270
  */
74
271
  export const environment = config.environment;
75
- // Logger initialization is now handled in the main application entry point (e.g., src/index.ts)
76
- // after the config module has been fully loaded.
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @fileoverview Barrel file for the git working directory resource.
3
+ * @module src/mcp-server/resources/gitWorkingDir/index
4
+ */
5
+ export * from "./registration.js";
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @fileoverview Defines the core logic for the git working directory resource.
3
+ * @module src/mcp-server/resources/gitWorkingDir/logic
4
+ */
5
+ import { logger } from "../../../utils/index.js";
6
+ /**
7
+ * Retrieves the current working directory for the session.
8
+ * @param context The request context for logging and tracing.
9
+ * @param getWorkingDirectory Function to get the session's working directory.
10
+ * @param sessionId The ID of the current session.
11
+ * @returns The current working directory path or 'NOT_SET'.
12
+ */
13
+ export function getGitWorkingDirLogic(context, getWorkingDirectory, sessionId) {
14
+ logger.debug("Executing getGitWorkingDirLogic...", { ...context, sessionId });
15
+ const workingDir = getWorkingDirectory(sessionId);
16
+ return workingDir ?? "NOT_SET";
17
+ }