Skip to content

Commit c3f7967

Browse files
authored
Feature/docker support (#2)
* feat: add Docker support with path validation fix - Add Dockerfile with multi-stage Bun build on Debian - Optimize .dockerignore for smaller build context - Fix path resolution bug that caused ENOENT errors (PR cyanheads#33) * ci: add GHCR Docker image build workflow - Build and push to ghcr.io on main branch push - Multi-platform support (amd64, arm64) - Semantic versioning tags on release - Manual trigger with custom tag support * fix(clone): run git clone from parent directory to avoid ENOENT Resolves issue where clone failed with 'posix_spawn git' error because the target directory doesn't exist yet. Now clones from parent dir. Ref: cyanheads#33 * feat(clone): enhance URL validation for repository cloning Updated the input schema to enforce a minimum length for the repository URL and clarified the supported URL formats (HTTPS and SSH) in the description. This improves user guidance and input validation for the git clone tool.
2 parents 4517cb1 + e180322 commit c3f7967

File tree

2 files changed

+19
-4
lines changed

2 files changed

+19
-4
lines changed

src/mcp-server/tools/definitions/git-clone.tool.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@ const TOOL_DESCRIPTION =
2222
'Clone a repository from a remote URL to a local path. Supports HTTP/HTTPS and SSH URLs, with optional shallow cloning.';
2323

2424
const InputSchema = z.object({
25-
url: z.string().url().describe('Remote repository URL to clone from.'),
25+
url: z
26+
.string()
27+
.min(1)
28+
.describe(
29+
'Remote repository URL to clone from. Supports HTTPS (https://github.com/user/repo.git) and SSH ([email protected]:user/repo.git) formats.',
30+
),
2631
localPath: z
2732
.string()
2833
.min(1)

src/services/git/providers/cli/operations/core/clone.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* @module services/git/providers/cli/operations/core/clone
44
*/
55

6+
import * as path from 'node:path';
7+
68
import type { RequestContext } from '@/utils/index.js';
79

810
import type {
@@ -25,7 +27,14 @@ export async function executeClone(
2527
) => Promise<{ stdout: string; stderr: string }>,
2628
): Promise<GitCloneResult> {
2729
try {
28-
const args: string[] = [options.remoteUrl, options.localPath];
30+
// Resolve localPath to absolute and get parent directory
31+
// Clone must run from parent dir since target doesn't exist yet
32+
// See: https://github.com/cyanheads/git-mcp-server/pull/33
33+
const absoluteLocalPath = path.resolve(options.localPath);
34+
const parentDir = path.dirname(absoluteLocalPath);
35+
const targetDirName = path.basename(absoluteLocalPath);
36+
37+
const args: string[] = [options.remoteUrl, targetDirName];
2938

3039
if (options.branch) {
3140
args.push('--branch', options.branch);
@@ -48,11 +57,12 @@ export async function executeClone(
4857
}
4958

5059
const cmd = buildGitCommand({ command: 'clone', args });
51-
await execGit(cmd, context.workingDirectory, context.requestContext);
60+
// Run from parent directory, clone into target directory name
61+
await execGit(cmd, parentDir, context.requestContext);
5262

5363
const result = {
5464
success: true,
55-
localPath: options.localPath,
65+
localPath: absoluteLocalPath,
5666
remoteUrl: options.remoteUrl,
5767
branch: options.branch || 'main',
5868
};

0 commit comments

Comments
 (0)