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
package/dist/index.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Merlin MCP Server - Entry Point
|
|
4
|
+
*
|
|
5
|
+
* AI-powered codebase intelligence for coding agents.
|
|
6
|
+
* https://merlin.build
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* npx merlin-mcp
|
|
10
|
+
* MERLIN_API_KEY=xxx npx merlin-mcp
|
|
11
|
+
*
|
|
12
|
+
* Configuration (via environment variables):
|
|
13
|
+
* MERLIN_API_KEY - Your Merlin API key (required for private repos)
|
|
14
|
+
* MERLIN_API_URL - API base URL (default: https://api.merlin.build)
|
|
15
|
+
*/
|
|
16
|
+
import { startServer } from './server.js';
|
|
17
|
+
const CURRENT_VERSION = '0.2.0';
|
|
18
|
+
/** Check for updates on startup */
|
|
19
|
+
async function checkForUpdates() {
|
|
20
|
+
try {
|
|
21
|
+
const apiUrl = process.env.MERLIN_API_URL || 'https://claude-codeapi-production.up.railway.app';
|
|
22
|
+
const response = await fetch(`${apiUrl}/api/mcp/version`, {
|
|
23
|
+
headers: { 'User-Agent': `merlin-mcp/${CURRENT_VERSION}` },
|
|
24
|
+
signal: AbortSignal.timeout(3000),
|
|
25
|
+
});
|
|
26
|
+
if (!response.ok)
|
|
27
|
+
return;
|
|
28
|
+
const data = await response.json();
|
|
29
|
+
if (data.latest && data.latest !== CURRENT_VERSION) {
|
|
30
|
+
const current = CURRENT_VERSION.split('.').map(Number);
|
|
31
|
+
const latest = data.latest.split('.').map(Number);
|
|
32
|
+
const isOutdated = latest[0] > current[0] ||
|
|
33
|
+
(latest[0] === current[0] && latest[1] > current[1]) ||
|
|
34
|
+
(latest[0] === current[0] && latest[1] === current[1] && latest[2] > current[2]);
|
|
35
|
+
if (isOutdated) {
|
|
36
|
+
console.error(`\n⚠️ Update available: ${CURRENT_VERSION} → ${data.latest}`);
|
|
37
|
+
console.error(` Run: npx merlin-mcp@latest`);
|
|
38
|
+
console.error(` Or: npx clear-npx-cache && restart Claude Code\n`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// Silently ignore update check failures
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Check for help flag
|
|
47
|
+
if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
|
48
|
+
console.log(`
|
|
49
|
+
Merlin MCP Server
|
|
50
|
+
=================
|
|
51
|
+
|
|
52
|
+
AI-powered codebase intelligence for coding agents.
|
|
53
|
+
|
|
54
|
+
USAGE:
|
|
55
|
+
npx merlin-mcp Start the MCP server
|
|
56
|
+
npx merlin-mcp --help Show this help message
|
|
57
|
+
npx merlin-mcp --version Show version
|
|
58
|
+
|
|
59
|
+
CONFIGURATION:
|
|
60
|
+
Set these environment variables before running:
|
|
61
|
+
|
|
62
|
+
MERLIN_API_KEY Your Merlin API key (get it from merlin.build/settings)
|
|
63
|
+
MERLIN_API_URL API base URL (default: https://api.merlin.build)
|
|
64
|
+
|
|
65
|
+
CLAUDE CODE SETUP:
|
|
66
|
+
Add to ~/.claude/config.json:
|
|
67
|
+
|
|
68
|
+
{
|
|
69
|
+
"mcpServers": {
|
|
70
|
+
"merlin": {
|
|
71
|
+
"command": "npx",
|
|
72
|
+
"args": ["merlin-mcp"],
|
|
73
|
+
"env": {
|
|
74
|
+
"MERLIN_API_KEY": "your-api-key-here"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
AVAILABLE TOOLS (once connected):
|
|
81
|
+
merlin_get_context Get relevant context for a task
|
|
82
|
+
merlin_find_files Find files by purpose or layer
|
|
83
|
+
merlin_get_conventions Get coding conventions and anti-patterns
|
|
84
|
+
merlin_quickstart Get a 60-second codebase overview
|
|
85
|
+
merlin_search Search documentation
|
|
86
|
+
merlin_list_repos List your analyzed repositories
|
|
87
|
+
|
|
88
|
+
MORE INFO:
|
|
89
|
+
https://merlin.build/docs
|
|
90
|
+
`);
|
|
91
|
+
process.exit(0);
|
|
92
|
+
}
|
|
93
|
+
// Check for version flag
|
|
94
|
+
if (process.argv.includes('--version') || process.argv.includes('-v')) {
|
|
95
|
+
console.log(CURRENT_VERSION);
|
|
96
|
+
process.exit(0);
|
|
97
|
+
}
|
|
98
|
+
// Check for missing API key and show helpful message
|
|
99
|
+
function checkApiKey() {
|
|
100
|
+
const apiKey = process.env.MERLIN_API_KEY;
|
|
101
|
+
if (!apiKey) {
|
|
102
|
+
console.error(`
|
|
103
|
+
┌─────────────────────────────────────────────────────────────────┐
|
|
104
|
+
│ │
|
|
105
|
+
│ 🔑 Merlin API Key Required │
|
|
106
|
+
│ │
|
|
107
|
+
│ To use Merlin Sights, you need an API key. │
|
|
108
|
+
│ │
|
|
109
|
+
│ Get your free API key at: │
|
|
110
|
+
│ 👉 https://merlin.build/settings │
|
|
111
|
+
│ │
|
|
112
|
+
│ Then configure Claude Code: │
|
|
113
|
+
│ │
|
|
114
|
+
│ claude mcp add merlin npx merlin-mcp \\ │
|
|
115
|
+
│ -e MERLIN_API_KEY=your-key-here --scope user │
|
|
116
|
+
│ │
|
|
117
|
+
│ Or add to ~/.claude/config.json: │
|
|
118
|
+
│ { │
|
|
119
|
+
│ "mcpServers": { │
|
|
120
|
+
│ "merlin": { │
|
|
121
|
+
│ "command": "npx", │
|
|
122
|
+
│ "args": ["merlin-mcp"], │
|
|
123
|
+
│ "env": { "MERLIN_API_KEY": "your-key-here" } │
|
|
124
|
+
│ } │
|
|
125
|
+
│ } │
|
|
126
|
+
│ } │
|
|
127
|
+
│ │
|
|
128
|
+
└─────────────────────────────────────────────────────────────────┘
|
|
129
|
+
`);
|
|
130
|
+
// Still start the server - tools will return helpful errors
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Start the server with update check
|
|
134
|
+
async function main() {
|
|
135
|
+
checkApiKey();
|
|
136
|
+
checkForUpdates();
|
|
137
|
+
await startServer();
|
|
138
|
+
}
|
|
139
|
+
main().catch(error => {
|
|
140
|
+
console.error('Failed to start Merlin MCP server:', error);
|
|
141
|
+
process.exit(1);
|
|
142
|
+
});
|
|
143
|
+
//# 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/dist/server.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merlin MCP Server
|
|
3
|
+
* AI-powered codebase intelligence for coding agents
|
|
4
|
+
* https://merlin.build
|
|
5
|
+
*/
|
|
6
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
|
+
/** Create and configure the MCP server */
|
|
8
|
+
export declare function createServer(): McpServer;
|
|
9
|
+
/** Start the MCP server with stdio transport */
|
|
10
|
+
export declare function startServer(): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMpE,0CAA0C;AAC1C,wBAAgB,YAAY,IAAI,SAAS,CAkhBxC;AAED,gDAAgD;AAChD,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAQjD"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merlin MCP Server
|
|
3
|
+
* AI-powered codebase intelligence for coding agents
|
|
4
|
+
* https://merlin.build
|
|
5
|
+
*/
|
|
6
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { getClient } from './api/client.js';
|
|
10
|
+
import { detectRepository } from './utils/git.js';
|
|
11
|
+
/** Create and configure the MCP server */
|
|
12
|
+
export function createServer() {
|
|
13
|
+
const server = new McpServer({
|
|
14
|
+
name: 'merlin',
|
|
15
|
+
version: '0.2.0',
|
|
16
|
+
description: 'Merlin - AI-powered codebase intelligence. Syncs every 5 min. ALWAYS fetch fresh context before coding.',
|
|
17
|
+
});
|
|
18
|
+
const client = getClient();
|
|
19
|
+
// Cache for resolved repo IDs to avoid repeated git/API calls
|
|
20
|
+
// Key: url or 'auto' for auto-detected, Value: { repoId, expiresAt }
|
|
21
|
+
const repoIdCache = new Map();
|
|
22
|
+
const REPO_ID_CACHE_TTL = 5 * 60 * 1000; // 5 minutes - repo ID won't change mid-session
|
|
23
|
+
// Helper to resolve repo ID from URL or auto-detect
|
|
24
|
+
async function resolveRepoId(repoUrl) {
|
|
25
|
+
const cacheKey = repoUrl || 'auto';
|
|
26
|
+
// Check cache first
|
|
27
|
+
const cached = repoIdCache.get(cacheKey);
|
|
28
|
+
if (cached && Date.now() < cached.expiresAt) {
|
|
29
|
+
return cached.repoId;
|
|
30
|
+
}
|
|
31
|
+
let url = repoUrl;
|
|
32
|
+
// Auto-detect from git if not provided
|
|
33
|
+
if (!url) {
|
|
34
|
+
const detected = await detectRepository();
|
|
35
|
+
if (!detected) {
|
|
36
|
+
// Cache the null result to avoid repeated git commands
|
|
37
|
+
repoIdCache.set(cacheKey, { repoId: null, expiresAt: Date.now() + 60000 }); // 1 min for failures
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
url = detected.url;
|
|
41
|
+
}
|
|
42
|
+
// Find repo in Merlin
|
|
43
|
+
const repo = await client.findRepoByUrl(url);
|
|
44
|
+
const repoId = repo?.id || null;
|
|
45
|
+
// Cache the result
|
|
46
|
+
repoIdCache.set(cacheKey, { repoId, expiresAt: Date.now() + REPO_ID_CACHE_TTL });
|
|
47
|
+
return repoId;
|
|
48
|
+
}
|
|
49
|
+
// ============================================================
|
|
50
|
+
// TOOLS
|
|
51
|
+
// ============================================================
|
|
52
|
+
// Tool: merlin_get_context
|
|
53
|
+
server.tool('merlin_get_context', 'ALWAYS CALL THIS FIRST for ANY codebase question. Wiki syncs every 5 minutes so ALWAYS fetch fresh - never rely on what you read earlier in this conversation. Call this tool again if more than a few minutes have passed or before any implementation work.', {
|
|
54
|
+
task: z.string().describe('What you want to know or do (e.g., "how does profile creation work", "add authentication", "where is the payment logic")'),
|
|
55
|
+
repoUrl: z.string().optional().describe('GitHub URL of the repository (auto-detected from git if omitted)'),
|
|
56
|
+
}, async ({ task, repoUrl }) => {
|
|
57
|
+
try {
|
|
58
|
+
const repoId = await resolveRepoId(repoUrl);
|
|
59
|
+
if (!repoId) {
|
|
60
|
+
return {
|
|
61
|
+
content: [{
|
|
62
|
+
type: 'text',
|
|
63
|
+
text: 'Could not find repository. Make sure:\n1. You are in a git repository\n2. The repository has been analyzed on merlin.build\n3. Or provide the repoUrl parameter explicitly',
|
|
64
|
+
}],
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
// Get how-to guide for the task
|
|
68
|
+
const howTo = await client.getHowTo(repoId, task);
|
|
69
|
+
// Get relevant files
|
|
70
|
+
const files = await client.getFiles(repoId, { purpose: task });
|
|
71
|
+
// Get conventions
|
|
72
|
+
const conventions = await client.getConventions(repoId);
|
|
73
|
+
// Build comprehensive context
|
|
74
|
+
let context = `# Context for: ${task}\n\n`;
|
|
75
|
+
context += `## How To Guide\n${howTo}\n\n`;
|
|
76
|
+
if (files.files.length > 0) {
|
|
77
|
+
context += `## Relevant Files (${files.count} total)\n`;
|
|
78
|
+
// Show all files - agents benefit from complete context
|
|
79
|
+
files.files.forEach(f => {
|
|
80
|
+
context += `- **${f.path}**: ${f.purpose}\n`;
|
|
81
|
+
if (f.exports.length > 0) {
|
|
82
|
+
context += ` Exports: ${f.exports.map(e => e.name).join(', ')}\n`;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
context += '\n';
|
|
86
|
+
}
|
|
87
|
+
if (conventions.conventions.length > 0) {
|
|
88
|
+
context += `## Conventions to Follow\n`;
|
|
89
|
+
// Show all conventions - they're important for correct implementation
|
|
90
|
+
conventions.conventions.forEach(c => {
|
|
91
|
+
context += `- **${c.category}**: ${c.rule}\n`;
|
|
92
|
+
if (c.example) {
|
|
93
|
+
context += ` Example: ${c.example}\n`;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
context += '\n';
|
|
97
|
+
}
|
|
98
|
+
if (conventions.antiPatterns.length > 0) {
|
|
99
|
+
context += `## Anti-Patterns to Avoid\n`;
|
|
100
|
+
// Show all anti-patterns - critical for code quality
|
|
101
|
+
conventions.antiPatterns.forEach(ap => {
|
|
102
|
+
context += `- ❌ ${ap.pattern}\n`;
|
|
103
|
+
context += ` → Instead: ${ap.instead}\n`;
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
content: [{
|
|
108
|
+
type: 'text',
|
|
109
|
+
text: context,
|
|
110
|
+
}],
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
return {
|
|
115
|
+
content: [{
|
|
116
|
+
type: 'text',
|
|
117
|
+
text: `Error getting context: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
118
|
+
}],
|
|
119
|
+
isError: true,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
// Tool: merlin_find_files
|
|
124
|
+
server.tool('merlin_find_files', 'Find files by purpose or layer. ALWAYS re-fetch before editing - files may have changed since you last checked. Returns file paths with descriptions.', {
|
|
125
|
+
query: z.string().describe('What you are looking for (e.g., "authentication", "database models", "API routes", "payment handling")'),
|
|
126
|
+
layer: z.string().optional().describe('Filter by layer (routes, services, models, utils, components, etc.)'),
|
|
127
|
+
repoUrl: z.string().optional().describe('GitHub URL of the repository (auto-detected from git if omitted)'),
|
|
128
|
+
}, async ({ query, layer, repoUrl }) => {
|
|
129
|
+
try {
|
|
130
|
+
const repoId = await resolveRepoId(repoUrl);
|
|
131
|
+
if (!repoId) {
|
|
132
|
+
return {
|
|
133
|
+
content: [{
|
|
134
|
+
type: 'text',
|
|
135
|
+
text: 'Could not find repository. Make sure the repo is analyzed on merlin.build.',
|
|
136
|
+
}],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
// Try structured file query first
|
|
140
|
+
const files = await client.getFiles(repoId, { layer, purpose: query });
|
|
141
|
+
if (files.files.length > 0) {
|
|
142
|
+
let result = `# Files matching "${query}"${layer ? ` in ${layer} layer` : ''}\n\n`;
|
|
143
|
+
result += `Found ${files.count} files:\n\n`;
|
|
144
|
+
files.files.forEach(f => {
|
|
145
|
+
result += `## ${f.path}\n`;
|
|
146
|
+
result += `- **Purpose**: ${f.purpose}\n`;
|
|
147
|
+
result += `- **Layer**: ${f.layer}\n`;
|
|
148
|
+
if (f.exports.length > 0) {
|
|
149
|
+
result += `- **Exports**: ${f.exports.map(e => `${e.name} (${e.type})`).join(', ')}\n`;
|
|
150
|
+
}
|
|
151
|
+
if (f.modifyFor.length > 0) {
|
|
152
|
+
result += `- **Modify for**: ${f.modifyFor.join(', ')}\n`;
|
|
153
|
+
}
|
|
154
|
+
result += '\n';
|
|
155
|
+
});
|
|
156
|
+
return { content: [{ type: 'text', text: result }] };
|
|
157
|
+
}
|
|
158
|
+
// Fall back to text-based find
|
|
159
|
+
const findResult = await client.findFiles(repoId, query);
|
|
160
|
+
return { content: [{ type: 'text', text: findResult }] };
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
return {
|
|
164
|
+
content: [{
|
|
165
|
+
type: 'text',
|
|
166
|
+
text: `Error finding files: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
167
|
+
}],
|
|
168
|
+
isError: true,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
// Tool: merlin_get_conventions
|
|
173
|
+
server.tool('merlin_get_conventions', 'Get coding conventions and anti-patterns for the repository.', {
|
|
174
|
+
repoUrl: z.string().optional().describe('GitHub URL of the repository (auto-detected from git if omitted)'),
|
|
175
|
+
}, async ({ repoUrl }) => {
|
|
176
|
+
try {
|
|
177
|
+
const repoId = await resolveRepoId(repoUrl);
|
|
178
|
+
if (!repoId) {
|
|
179
|
+
return {
|
|
180
|
+
content: [{
|
|
181
|
+
type: 'text',
|
|
182
|
+
text: 'Could not find repository. Make sure the repo is analyzed on merlin.build.',
|
|
183
|
+
}],
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
const conventions = await client.getConventions(repoId);
|
|
187
|
+
let result = '# Coding Conventions\n\n';
|
|
188
|
+
if (conventions.conventions.length > 0) {
|
|
189
|
+
result += '## Conventions\n\n';
|
|
190
|
+
conventions.conventions.forEach(c => {
|
|
191
|
+
result += `### ${c.category}\n`;
|
|
192
|
+
result += `${c.rule}\n`;
|
|
193
|
+
if (c.example) {
|
|
194
|
+
result += `\n**Example:**\n\`\`\`\n${c.example}\n\`\`\`\n`;
|
|
195
|
+
}
|
|
196
|
+
if (c.exampleFiles.length > 0) {
|
|
197
|
+
result += `\n**See**: ${c.exampleFiles.join(', ')}\n`;
|
|
198
|
+
}
|
|
199
|
+
result += '\n';
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
if (conventions.antiPatterns.length > 0) {
|
|
203
|
+
result += '## Anti-Patterns (Avoid These)\n\n';
|
|
204
|
+
conventions.antiPatterns.forEach(ap => {
|
|
205
|
+
result += `### ❌ ${ap.pattern}\n`;
|
|
206
|
+
result += `**Reason**: ${ap.reason}\n`;
|
|
207
|
+
result += `**Instead**: ${ap.instead}\n`;
|
|
208
|
+
result += `**Severity**: ${ap.severity}\n\n`;
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
if (conventions.changeGuides.length > 0) {
|
|
212
|
+
result += '## Change Guides\n\n';
|
|
213
|
+
conventions.changeGuides.slice(0, 5).forEach(cg => {
|
|
214
|
+
result += `### ${cg.task}\n`;
|
|
215
|
+
result += `${cg.description}\n\n`;
|
|
216
|
+
result += '**Steps:**\n';
|
|
217
|
+
cg.steps.forEach(s => {
|
|
218
|
+
result += `${s.order}. ${s.file}: ${s.description}\n`;
|
|
219
|
+
});
|
|
220
|
+
result += '\n';
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
return { content: [{ type: 'text', text: result }] };
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
return {
|
|
227
|
+
content: [{
|
|
228
|
+
type: 'text',
|
|
229
|
+
text: `Error getting conventions: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
230
|
+
}],
|
|
231
|
+
isError: true,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
// Tool: merlin_quickstart
|
|
236
|
+
server.tool('merlin_quickstart', 'Get a 60-second overview of the codebase. Use this when first working with a repository.', {
|
|
237
|
+
repoUrl: z.string().optional().describe('GitHub URL of the repository (auto-detected from git if omitted)'),
|
|
238
|
+
}, async ({ repoUrl }) => {
|
|
239
|
+
try {
|
|
240
|
+
const repoId = await resolveRepoId(repoUrl);
|
|
241
|
+
if (!repoId) {
|
|
242
|
+
return {
|
|
243
|
+
content: [{
|
|
244
|
+
type: 'text',
|
|
245
|
+
text: 'Could not find repository. Make sure the repo is analyzed on merlin.build.',
|
|
246
|
+
}],
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
const quickstart = await client.getQuickstart(repoId);
|
|
250
|
+
return { content: [{ type: 'text', text: quickstart }] };
|
|
251
|
+
}
|
|
252
|
+
catch (error) {
|
|
253
|
+
return {
|
|
254
|
+
content: [{
|
|
255
|
+
type: 'text',
|
|
256
|
+
text: `Error getting quickstart: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
257
|
+
}],
|
|
258
|
+
isError: true,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
// Tool: merlin_search
|
|
263
|
+
server.tool('merlin_search', 'Search project documentation. Wiki updates in real-time as team commits code, so ALWAYS search fresh - never assume earlier results are still accurate.', {
|
|
264
|
+
query: z.string().describe('What you want to find (e.g., "profile creation flow", "authentication", "payment API")'),
|
|
265
|
+
repoUrl: z.string().optional().describe('GitHub URL of the repository (auto-detected from git if omitted)'),
|
|
266
|
+
}, async ({ query, repoUrl }) => {
|
|
267
|
+
try {
|
|
268
|
+
const repoId = await resolveRepoId(repoUrl);
|
|
269
|
+
if (!repoId) {
|
|
270
|
+
return {
|
|
271
|
+
content: [{
|
|
272
|
+
type: 'text',
|
|
273
|
+
text: 'Could not find repository. Make sure the repo is analyzed on merlin.build.',
|
|
274
|
+
}],
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
const results = await client.search(repoId, query);
|
|
278
|
+
return { content: [{ type: 'text', text: results }] };
|
|
279
|
+
}
|
|
280
|
+
catch (error) {
|
|
281
|
+
return {
|
|
282
|
+
content: [{
|
|
283
|
+
type: 'text',
|
|
284
|
+
text: `Error searching: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
285
|
+
}],
|
|
286
|
+
isError: true,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
// Tool: merlin_list_repos
|
|
291
|
+
server.tool('merlin_list_repos', 'List all repositories you have analyzed on Merlin.', {}, async () => {
|
|
292
|
+
try {
|
|
293
|
+
const repos = await client.getRepositories();
|
|
294
|
+
if (repos.length === 0) {
|
|
295
|
+
return {
|
|
296
|
+
content: [{
|
|
297
|
+
type: 'text',
|
|
298
|
+
text: 'No repositories found. Visit merlin.build to analyze your first repository.',
|
|
299
|
+
}],
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
let result = '# Your Analyzed Repositories\n\n';
|
|
303
|
+
repos.forEach(repo => {
|
|
304
|
+
// Map status to agent-friendly names
|
|
305
|
+
// Never show "failed" - instead show "incomplete" so agents still try to get data
|
|
306
|
+
const status = repo.status;
|
|
307
|
+
let displayStatus = status;
|
|
308
|
+
let statusNote = '';
|
|
309
|
+
if (status === 'completed') {
|
|
310
|
+
displayStatus = 'ready';
|
|
311
|
+
}
|
|
312
|
+
else if (status === 'failed') {
|
|
313
|
+
// IMPORTANT: Don't tell agents it failed - there may still be partial data
|
|
314
|
+
displayStatus = 'incomplete';
|
|
315
|
+
statusNote = ' (some analysis data may be available)';
|
|
316
|
+
}
|
|
317
|
+
else if (status === 'processing' || status === 'analyzing') {
|
|
318
|
+
displayStatus = 'processing';
|
|
319
|
+
statusNote = ' (check back soon)';
|
|
320
|
+
}
|
|
321
|
+
else if (status === 'pending' || status === 'queued') {
|
|
322
|
+
displayStatus = 'queued';
|
|
323
|
+
statusNote = ' (analysis starting soon)';
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
displayStatus = status || 'unknown';
|
|
327
|
+
}
|
|
328
|
+
result += `## ${repo.fullName || repo.name}\n`;
|
|
329
|
+
result += `- **URL**: ${repo.url}\n`;
|
|
330
|
+
result += `- **Branch**: ${repo.branch}\n`;
|
|
331
|
+
result += `- **Status**: ${displayStatus}${statusNote}\n`;
|
|
332
|
+
if (repo.lastAnalyzedAt) {
|
|
333
|
+
result += `- **Last Analyzed**: ${repo.lastAnalyzedAt}\n`;
|
|
334
|
+
}
|
|
335
|
+
result += '\n';
|
|
336
|
+
});
|
|
337
|
+
result += `\n---\n`;
|
|
338
|
+
result += `**Note**: Even for "incomplete" repos, try fetching context - partial data may be available.\n`;
|
|
339
|
+
return { content: [{ type: 'text', text: result }] };
|
|
340
|
+
}
|
|
341
|
+
catch (error) {
|
|
342
|
+
return {
|
|
343
|
+
content: [{
|
|
344
|
+
type: 'text',
|
|
345
|
+
text: `Error listing repos: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
346
|
+
}],
|
|
347
|
+
isError: true,
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
// Tool: merlin_impact_analysis
|
|
352
|
+
server.tool('merlin_impact_analysis', 'Analyze what could break if you change a specific file. Returns files that depend on this file and might need updates.', {
|
|
353
|
+
filePath: z.string().describe('The file path you plan to modify (e.g., "src/services/user.ts")'),
|
|
354
|
+
repoUrl: z.string().optional().describe('GitHub URL of the repository (auto-detected from git if omitted)'),
|
|
355
|
+
}, async ({ filePath, repoUrl }) => {
|
|
356
|
+
try {
|
|
357
|
+
const repoId = await resolveRepoId(repoUrl);
|
|
358
|
+
if (!repoId) {
|
|
359
|
+
return {
|
|
360
|
+
content: [{
|
|
361
|
+
type: 'text',
|
|
362
|
+
text: 'Could not find repository. Make sure the repo is analyzed on merlin.build.',
|
|
363
|
+
}],
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
const impact = await client.getImpactAnalysis(repoId, filePath);
|
|
367
|
+
return { content: [{ type: 'text', text: impact }] };
|
|
368
|
+
}
|
|
369
|
+
catch (error) {
|
|
370
|
+
return {
|
|
371
|
+
content: [{
|
|
372
|
+
type: 'text',
|
|
373
|
+
text: `Error analyzing impact: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
374
|
+
}],
|
|
375
|
+
isError: true,
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
// Tool: merlin_similar_code
|
|
380
|
+
server.tool('merlin_similar_code', 'Find similar implementations in the codebase. Use this when you need to see how something similar was done before.', {
|
|
381
|
+
description: z.string().describe('What you\'re trying to implement (e.g., "API endpoint with authentication", "database query with pagination", "React form with validation")'),
|
|
382
|
+
repoUrl: z.string().optional().describe('GitHub URL of the repository (auto-detected from git if omitted)'),
|
|
383
|
+
}, async ({ description, repoUrl }) => {
|
|
384
|
+
try {
|
|
385
|
+
const repoId = await resolveRepoId(repoUrl);
|
|
386
|
+
if (!repoId) {
|
|
387
|
+
return {
|
|
388
|
+
content: [{
|
|
389
|
+
type: 'text',
|
|
390
|
+
text: 'Could not find repository. Make sure the repo is analyzed on merlin.build.',
|
|
391
|
+
}],
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
const similar = await client.getSimilarCode(repoId, description);
|
|
395
|
+
return { content: [{ type: 'text', text: similar }] };
|
|
396
|
+
}
|
|
397
|
+
catch (error) {
|
|
398
|
+
return {
|
|
399
|
+
content: [{
|
|
400
|
+
type: 'text',
|
|
401
|
+
text: `Error finding similar code: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
402
|
+
}],
|
|
403
|
+
isError: true,
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
// Tool: merlin_code_examples
|
|
408
|
+
server.tool('merlin_code_examples', 'Get real code examples from this codebase for common tasks. Shows actual patterns used in this project.', {
|
|
409
|
+
task: z.string().optional().describe('Specific task (e.g., "add endpoint", "add test", "error handling"). Leave empty for all examples.'),
|
|
410
|
+
repoUrl: z.string().optional().describe('GitHub URL of the repository (auto-detected from git if omitted)'),
|
|
411
|
+
}, async ({ task, repoUrl }) => {
|
|
412
|
+
try {
|
|
413
|
+
const repoId = await resolveRepoId(repoUrl);
|
|
414
|
+
if (!repoId) {
|
|
415
|
+
return {
|
|
416
|
+
content: [{
|
|
417
|
+
type: 'text',
|
|
418
|
+
text: 'Could not find repository. Make sure the repo is analyzed on merlin.build.',
|
|
419
|
+
}],
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
const examples = await client.getCodeExamples(repoId, task);
|
|
423
|
+
return { content: [{ type: 'text', text: examples }] };
|
|
424
|
+
}
|
|
425
|
+
catch (error) {
|
|
426
|
+
return {
|
|
427
|
+
content: [{
|
|
428
|
+
type: 'text',
|
|
429
|
+
text: `Error getting code examples: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
430
|
+
}],
|
|
431
|
+
isError: true,
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
// ============================================================
|
|
436
|
+
// RESOURCES
|
|
437
|
+
// ============================================================
|
|
438
|
+
// Resource: List of repos
|
|
439
|
+
server.resource('repos', 'merlin://repos', {
|
|
440
|
+
description: 'List of all analyzed repositories',
|
|
441
|
+
mimeType: 'application/json',
|
|
442
|
+
}, async () => {
|
|
443
|
+
const repos = await client.getRepositories();
|
|
444
|
+
return {
|
|
445
|
+
contents: [{
|
|
446
|
+
uri: 'merlin://repos',
|
|
447
|
+
mimeType: 'application/json',
|
|
448
|
+
text: JSON.stringify(repos, null, 2),
|
|
449
|
+
}],
|
|
450
|
+
};
|
|
451
|
+
});
|
|
452
|
+
return server;
|
|
453
|
+
}
|
|
454
|
+
/** Start the MCP server with stdio transport */
|
|
455
|
+
export async function startServer() {
|
|
456
|
+
const server = createServer();
|
|
457
|
+
const transport = new StdioServerTransport();
|
|
458
|
+
await server.connect(transport);
|
|
459
|
+
// Log to stderr (stdout is used for MCP protocol)
|
|
460
|
+
console.error('Merlin MCP server started');
|
|
461
|
+
}
|
|
462
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|