merlin-mcp 0.2.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.
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Git Utilities
3
+ * Detect current repository from git configuration
4
+ */
5
+ /** Result of repository detection */
6
+ export interface RepoDetectionResult {
7
+ /** GitHub URL of the repository */
8
+ url: string;
9
+ /** Detected branch name */
10
+ branch: string;
11
+ /** Root directory of the repository */
12
+ rootDir: string;
13
+ }
14
+ /**
15
+ * Find the git root directory by walking up from current directory
16
+ */
17
+ export declare function findGitRoot(startDir?: string): Promise<string | null>;
18
+ /**
19
+ * Normalize a git remote URL to a standard GitHub URL format
20
+ */
21
+ export declare function normalizeGitUrl(url: string): string;
22
+ /**
23
+ * Detect the current repository from git configuration
24
+ */
25
+ export declare function detectRepository(workingDir?: string): Promise<RepoDetectionResult | null>;
26
+ /**
27
+ * Extract owner and repo name from a GitHub URL
28
+ */
29
+ export declare function parseGitHubUrl(url: string): {
30
+ owner: string;
31
+ repo: string;
32
+ } | null;
33
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,qCAAqC;AACrC,MAAM,WAAW,mBAAmB;IAClC,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiB3E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAcnD;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAoD/F;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAalF"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Git Utilities
3
+ * Detect current repository from git configuration
4
+ */
5
+ import { simpleGit } from 'simple-git';
6
+ import * as path from 'path';
7
+ import * as fs from 'fs';
8
+ /**
9
+ * Find the git root directory by walking up from current directory
10
+ */
11
+ export async function findGitRoot(startDir) {
12
+ let currentDir = startDir || process.cwd();
13
+ while (currentDir !== path.dirname(currentDir)) {
14
+ const gitDir = path.join(currentDir, '.git');
15
+ try {
16
+ const stat = await fs.promises.stat(gitDir);
17
+ if (stat.isDirectory() || stat.isFile()) {
18
+ return currentDir;
19
+ }
20
+ }
21
+ catch {
22
+ // .git doesn't exist here, keep walking up
23
+ }
24
+ currentDir = path.dirname(currentDir);
25
+ }
26
+ return null;
27
+ }
28
+ /**
29
+ * Normalize a git remote URL to a standard GitHub URL format
30
+ */
31
+ export function normalizeGitUrl(url) {
32
+ // Handle SSH URLs: git@github.com:owner/repo.git
33
+ if (url.startsWith('git@')) {
34
+ url = url
35
+ .replace(/^git@github\.com:/, 'https://github.com/')
36
+ .replace(/\.git$/, '');
37
+ }
38
+ // Handle HTTPS URLs: https://github.com/owner/repo.git
39
+ if (url.startsWith('https://') || url.startsWith('http://')) {
40
+ url = url.replace(/\.git$/, '');
41
+ }
42
+ return url;
43
+ }
44
+ /**
45
+ * Detect the current repository from git configuration
46
+ */
47
+ export async function detectRepository(workingDir) {
48
+ try {
49
+ // Find git root
50
+ const rootDir = await findGitRoot(workingDir);
51
+ if (!rootDir) {
52
+ return null;
53
+ }
54
+ const git = simpleGit(rootDir);
55
+ // Get remotes
56
+ const remotes = await git.getRemotes(true);
57
+ // Find origin or first remote with a GitHub URL
58
+ let remoteUrl = null;
59
+ // Prefer 'origin' remote
60
+ const origin = remotes.find(r => r.name === 'origin');
61
+ if (origin?.refs?.fetch) {
62
+ remoteUrl = origin.refs.fetch;
63
+ }
64
+ else if (origin?.refs?.push) {
65
+ remoteUrl = origin.refs.push;
66
+ }
67
+ // Fall back to any remote with a GitHub URL
68
+ if (!remoteUrl) {
69
+ for (const remote of remotes) {
70
+ const url = remote.refs?.fetch || remote.refs?.push;
71
+ if (url && url.includes('github.com')) {
72
+ remoteUrl = url;
73
+ break;
74
+ }
75
+ }
76
+ }
77
+ if (!remoteUrl) {
78
+ return null;
79
+ }
80
+ // Get current branch
81
+ const branchSummary = await git.branch();
82
+ const branch = branchSummary.current || 'main';
83
+ return {
84
+ url: normalizeGitUrl(remoteUrl),
85
+ branch,
86
+ rootDir,
87
+ };
88
+ }
89
+ catch (error) {
90
+ console.error('Error detecting repository:', error);
91
+ return null;
92
+ }
93
+ }
94
+ /**
95
+ * Extract owner and repo name from a GitHub URL
96
+ */
97
+ export function parseGitHubUrl(url) {
98
+ const normalized = normalizeGitUrl(url);
99
+ // Match https://github.com/owner/repo
100
+ const match = normalized.match(/github\.com\/([^\/]+)\/([^\/]+)/);
101
+ if (match) {
102
+ return {
103
+ owner: match[1],
104
+ repo: match[2],
105
+ };
106
+ }
107
+ return null;
108
+ }
109
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/utils/git.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "merlin-mcp",
3
+ "version": "0.2.0",
4
+ "description": "Merlin MCP Server - AI-powered codebase intelligence for coding agents",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "bin": {
8
+ "merlin-mcp": "./dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "README.md"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "dev": "tsx watch src/index.ts",
17
+ "start": "node dist/index.js",
18
+ "clean": "rm -rf dist",
19
+ "typecheck": "tsc --noEmit",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "keywords": [
23
+ "mcp",
24
+ "model-context-protocol",
25
+ "claude",
26
+ "claude-code",
27
+ "ai",
28
+ "coding-assistant",
29
+ "codebase-context"
30
+ ],
31
+ "author": "Merlin",
32
+ "license": "MIT",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/anthropics/merlin"
36
+ },
37
+ "homepage": "https://merlin.build",
38
+ "engines": {
39
+ "node": ">=18.0.0"
40
+ },
41
+ "dependencies": {
42
+ "@modelcontextprotocol/sdk": "^1.0.0",
43
+ "simple-git": "^3.21.0",
44
+ "zod": "^3.25.0"
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "^20.10.0",
48
+ "tsx": "^4.6.2",
49
+ "typescript": "^5.3.0"
50
+ }
51
+ }