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/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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"}
@@ -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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"}