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.
- package/README.md +148 -0
- package/dist/api/client.d.ts +58 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +205 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/types.d.ts +100 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +5 -0
- package/dist/api/types.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +143 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +11 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +462 -0
- package/dist/server.js.map +1 -0
- package/dist/utils/git.d.ts +33 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +109 -0
- package/dist/utils/git.js.map +1 -0
- package/package.json +51 -0
|
@@ -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
|
+
}
|