repack-logs-mcp 1.0.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 ADDED
@@ -0,0 +1,116 @@
1
+ # repack-logs-mcp
2
+
3
+ An MCP (Model Context Protocol) server for tailing Re.Pack/Rspack dev server logs. Enables AI assistants like Claude to query build logs, find errors, and monitor compilation status.
4
+
5
+ ## How It Works
6
+
7
+ Re.Pack supports `--log-file <path>` which outputs JSON log entries to a file. This MCP server watches that file and provides tools to query the logs.
8
+
9
+ ```bash
10
+ # Run your dev server with file logging
11
+ npx react-native start --log-file .repack-logs.json
12
+ ```
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install -g repack-logs-mcp
18
+ # or use directly with npx
19
+ npx repack-logs-mcp /path/to/.repack-logs.json
20
+ ```
21
+
22
+ ## Tools Provided
23
+
24
+ | Tool | Description |
25
+ |------|-------------|
26
+ | `get_build_logs` | Get recent logs with filters (type, limit, time, issuer, search) |
27
+ | `get_errors` | Get only errors and warnings |
28
+ | `clear_logs` | Clear the in-memory buffer |
29
+ | `get_status` | Show watcher status and statistics |
30
+
31
+ ## Configuration
32
+
33
+ The log file path can be set via:
34
+
35
+ 1. **CLI argument** (highest priority):
36
+ ```bash
37
+ npx repack-logs-mcp /path/to/.repack-logs.json
38
+ ```
39
+
40
+ 2. **Environment variable**:
41
+ ```bash
42
+ REPACK_LOG_FILE=/path/to/.repack-logs.json npx repack-logs-mcp
43
+ ```
44
+
45
+ 3. **Default**: `.repack-logs.json` in current directory
46
+
47
+ ### Environment Variables
48
+
49
+ | Variable | Description | Default |
50
+ |----------|-------------|---------|
51
+ | `REPACK_LOG_FILE` | Path to the log file | `.repack-logs.json` |
52
+ | `REPACK_MAX_LOGS` | Maximum logs to keep in memory | `1000` |
53
+
54
+ ## Claude Code Integration
55
+
56
+ Add to your Claude Code MCP settings (`~/.claude/settings.json` or project settings):
57
+
58
+ ```json
59
+ {
60
+ "mcpServers": {
61
+ "repack-logs": {
62
+ "command": "npx",
63
+ "args": ["repack-logs-mcp", "/path/to/your/project/.repack-logs.json"]
64
+ }
65
+ }
66
+ }
67
+ ```
68
+
69
+ Then ask Claude things like:
70
+ - "What are the recent build logs?"
71
+ - "Are there any build errors?"
72
+ - "Show me warnings from the last build"
73
+ - "What's the status of the log watcher?"
74
+
75
+ ## Usage Examples
76
+
77
+ ### Get recent logs
78
+ ```
79
+ Tool: get_build_logs
80
+ Args: { "limit": 10 }
81
+ ```
82
+
83
+ ### Filter by type
84
+ ```
85
+ Tool: get_build_logs
86
+ Args: { "types": ["error", "warn"], "limit": 20 }
87
+ ```
88
+
89
+ ### Search logs
90
+ ```
91
+ Tool: get_build_logs
92
+ Args: { "search": "Cannot find module" }
93
+ ```
94
+
95
+ ### Get errors only
96
+ ```
97
+ Tool: get_errors
98
+ Args: { "limit": 10 }
99
+ ```
100
+
101
+ ## Development
102
+
103
+ ```bash
104
+ # Install dependencies
105
+ npm install
106
+
107
+ # Build
108
+ npm run build
109
+
110
+ # Test with MCP Inspector
111
+ npx @modelcontextprotocol/inspector node dist/index.js .repack-logs.json
112
+ ```
113
+
114
+ ## License
115
+
116
+ MIT
@@ -0,0 +1,14 @@
1
+ export interface Config {
2
+ logFilePath: string;
3
+ maxLogs: number;
4
+ }
5
+ /**
6
+ * Parse configuration from CLI args and environment variables.
7
+ *
8
+ * Priority:
9
+ * 1. CLI argument (first positional arg)
10
+ * 2. REPACK_LOG_FILE environment variable
11
+ * 3. Default: .repack-logs.json in current directory
12
+ */
13
+ export declare function getConfig(): Config;
14
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,MAAM;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB;AAKD;;;;;;;GAOG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAkBlC"}
package/dist/config.js ADDED
@@ -0,0 +1,27 @@
1
+ import { resolve } from 'path';
2
+ const DEFAULT_LOG_FILE = '.repack-logs.json';
3
+ const DEFAULT_MAX_LOGS = 1000;
4
+ /**
5
+ * Parse configuration from CLI args and environment variables.
6
+ *
7
+ * Priority:
8
+ * 1. CLI argument (first positional arg)
9
+ * 2. REPACK_LOG_FILE environment variable
10
+ * 3. Default: .repack-logs.json in current directory
11
+ */
12
+ export function getConfig() {
13
+ const args = process.argv.slice(2);
14
+ // First positional argument is the log file path
15
+ const cliPath = args.find(arg => !arg.startsWith('-'));
16
+ const logFilePath = cliPath
17
+ ?? process.env.REPACK_LOG_FILE
18
+ ?? DEFAULT_LOG_FILE;
19
+ const maxLogs = process.env.REPACK_MAX_LOGS
20
+ ? parseInt(process.env.REPACK_MAX_LOGS, 10)
21
+ : DEFAULT_MAX_LOGS;
22
+ return {
23
+ logFilePath: resolve(logFilePath),
24
+ maxLogs,
25
+ };
26
+ }
27
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAO/B,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AAC7C,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAE9B;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS;IACvB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,iDAAiD;IACjD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAEvD,MAAM,WAAW,GAAG,OAAO;WACtB,OAAO,CAAC,GAAG,CAAC,eAAe;WAC3B,gBAAgB,CAAC;IAEtB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe;QACzC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,EAAE,CAAC;QAC3C,CAAC,CAAC,gBAAgB,CAAC;IAErB,OAAO;QACL,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC;QACjC,OAAO;KACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { z } from 'zod';
5
+ import { getConfig } from './config.js';
6
+ import { LogStore } from './log-store.js';
7
+ import { LogWatcher } from './log-watcher.js';
8
+ const config = getConfig();
9
+ const store = new LogStore(config.maxLogs);
10
+ const watcher = new LogWatcher(config.logFilePath, store);
11
+ // Create MCP server
12
+ const server = new McpServer({
13
+ name: 'repack-logs-mcp',
14
+ version: '1.0.0',
15
+ });
16
+ // Tool: get_build_logs
17
+ server.tool('get_build_logs', 'Get recent Re.Pack build logs with optional filtering', {
18
+ limit: z.number().optional().describe('Maximum number of logs to return (default: 50)'),
19
+ types: z.array(z.enum(['info', 'warn', 'error', 'debug', 'success', 'progress']))
20
+ .optional()
21
+ .describe('Filter by log type(s)'),
22
+ since: z.string().optional().describe('Only logs after this ISO timestamp'),
23
+ issuer: z.string().optional().describe('Filter by issuer/source name'),
24
+ search: z.string().optional().describe('Search in log messages'),
25
+ }, async (args) => {
26
+ const logs = store.get({
27
+ limit: args.limit ?? 50,
28
+ types: args.types,
29
+ since: args.since,
30
+ issuer: args.issuer,
31
+ search: args.search,
32
+ });
33
+ if (logs.length === 0) {
34
+ return {
35
+ content: [{
36
+ type: 'text',
37
+ text: 'No logs found matching the criteria.',
38
+ }],
39
+ };
40
+ }
41
+ const formatted = logs.map(log => {
42
+ const parts = [
43
+ `[${log.timestamp}]`,
44
+ `[${log.type.toUpperCase()}]`,
45
+ ];
46
+ if (log.issuer)
47
+ parts.push(`[${log.issuer}]`);
48
+ parts.push(log.message);
49
+ if (log.file)
50
+ parts.push(`\n File: ${log.file}`);
51
+ if (log.stack)
52
+ parts.push(`\n Stack: ${log.stack}`);
53
+ return parts.join(' ');
54
+ }).join('\n\n');
55
+ return {
56
+ content: [{
57
+ type: 'text',
58
+ text: `Found ${logs.length} log(s):\n\n${formatted}`,
59
+ }],
60
+ };
61
+ });
62
+ // Tool: get_errors
63
+ server.tool('get_errors', 'Get only errors and warnings from Re.Pack build logs', {
64
+ limit: z.number().optional().describe('Maximum number of errors to return (default: 20)'),
65
+ }, async (args) => {
66
+ const errors = store.getErrors(args.limit ?? 20);
67
+ if (errors.length === 0) {
68
+ return {
69
+ content: [{
70
+ type: 'text',
71
+ text: 'No errors or warnings found.',
72
+ }],
73
+ };
74
+ }
75
+ const formatted = errors.map(log => {
76
+ const icon = log.type === 'error' ? '❌' : '⚠️';
77
+ const parts = [
78
+ `${icon} [${log.timestamp}]`,
79
+ `[${log.type.toUpperCase()}]`,
80
+ ];
81
+ if (log.issuer)
82
+ parts.push(`[${log.issuer}]`);
83
+ parts.push(log.message);
84
+ if (log.file)
85
+ parts.push(`\n File: ${log.file}`);
86
+ if (log.stack)
87
+ parts.push(`\n Stack: ${log.stack}`);
88
+ return parts.join(' ');
89
+ }).join('\n\n');
90
+ const errorCount = errors.filter(e => e.type === 'error').length;
91
+ const warnCount = errors.filter(e => e.type === 'warn').length;
92
+ return {
93
+ content: [{
94
+ type: 'text',
95
+ text: `Found ${errorCount} error(s) and ${warnCount} warning(s):\n\n${formatted}`,
96
+ }],
97
+ };
98
+ });
99
+ // Tool: clear_logs
100
+ server.tool('clear_logs', 'Clear all logs from the in-memory buffer', {}, async () => {
101
+ const count = store.count;
102
+ store.clear();
103
+ return {
104
+ content: [{
105
+ type: 'text',
106
+ text: `Cleared ${count} log(s) from buffer.`,
107
+ }],
108
+ };
109
+ });
110
+ // Tool: get_status
111
+ server.tool('get_status', 'Get the current status of the log watcher', {}, async () => {
112
+ const status = {
113
+ watching: watcher.isWatching,
114
+ filePath: watcher.path,
115
+ fileExists: watcher.fileExists,
116
+ logCount: store.count,
117
+ errorCount: store.countByType('error'),
118
+ warningCount: store.countByType('warn'),
119
+ lastUpdate: store.lastTimestamp,
120
+ };
121
+ const lines = [
122
+ `Watcher Status:`,
123
+ ` Watching: ${status.watching ? 'Yes' : 'No'}`,
124
+ ` Log File: ${status.filePath}`,
125
+ ` File Exists: ${status.fileExists ? 'Yes' : 'No'}`,
126
+ ``,
127
+ `Log Statistics:`,
128
+ ` Total Logs: ${status.logCount}`,
129
+ ` Errors: ${status.errorCount}`,
130
+ ` Warnings: ${status.warningCount}`,
131
+ ` Last Update: ${status.lastUpdate ?? 'Never'}`,
132
+ ];
133
+ return {
134
+ content: [{
135
+ type: 'text',
136
+ text: lines.join('\n'),
137
+ }],
138
+ };
139
+ });
140
+ // Start the server
141
+ async function main() {
142
+ // Start watching the log file
143
+ await watcher.start();
144
+ // Connect via stdio
145
+ const transport = new StdioServerTransport();
146
+ await server.connect(transport);
147
+ // Handle shutdown
148
+ process.on('SIGINT', async () => {
149
+ await watcher.stop();
150
+ process.exit(0);
151
+ });
152
+ process.on('SIGTERM', async () => {
153
+ await watcher.stop();
154
+ process.exit(0);
155
+ });
156
+ }
157
+ main().catch((error) => {
158
+ console.error('Failed to start MCP server:', error);
159
+ process.exit(1);
160
+ });
161
+ //# 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,43 @@
1
+ import type { LogEntry, LogFilter, LogType } from './types.js';
2
+ /**
3
+ * In-memory circular buffer for storing log entries.
4
+ */
5
+ export declare class LogStore {
6
+ private logs;
7
+ private maxSize;
8
+ constructor(maxSize?: number);
9
+ /**
10
+ * Add a log entry to the store.
11
+ * Removes oldest entries if buffer is full.
12
+ */
13
+ add(entry: LogEntry): void;
14
+ /**
15
+ * Add multiple log entries at once.
16
+ */
17
+ addMany(entries: LogEntry[]): void;
18
+ /**
19
+ * Get logs with optional filtering.
20
+ */
21
+ get(filter?: LogFilter): LogEntry[];
22
+ /**
23
+ * Get only errors and warnings.
24
+ */
25
+ getErrors(limit?: number): LogEntry[];
26
+ /**
27
+ * Count logs by type.
28
+ */
29
+ countByType(type: LogType): number;
30
+ /**
31
+ * Get total log count.
32
+ */
33
+ get count(): number;
34
+ /**
35
+ * Get the timestamp of the most recent log.
36
+ */
37
+ get lastTimestamp(): string | null;
38
+ /**
39
+ * Clear all logs from the store.
40
+ */
41
+ clear(): void;
42
+ }
43
+ //# sourceMappingURL=log-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-store.d.ts","sourceRoot":"","sources":["../src/log-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE/D;;GAEG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,IAAI,CAAkB;IAC9B,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,GAAE,MAAa;IAIlC;;;OAGG;IACH,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAS1B;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI;IAMlC;;OAEG;IACH,GAAG,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,EAAE;IAoCnC;;OAEG;IACH,SAAS,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,EAAE;IAOrC;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM;IAIlC;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,CAElB;IAED;;OAEG;IACH,IAAI,aAAa,IAAI,MAAM,GAAG,IAAI,CAGjC;IAED;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * In-memory circular buffer for storing log entries.
3
+ */
4
+ export class LogStore {
5
+ logs = [];
6
+ maxSize;
7
+ constructor(maxSize = 1000) {
8
+ this.maxSize = maxSize;
9
+ }
10
+ /**
11
+ * Add a log entry to the store.
12
+ * Removes oldest entries if buffer is full.
13
+ */
14
+ add(entry) {
15
+ this.logs.push(entry);
16
+ // Trim if over max size
17
+ if (this.logs.length > this.maxSize) {
18
+ this.logs = this.logs.slice(-this.maxSize);
19
+ }
20
+ }
21
+ /**
22
+ * Add multiple log entries at once.
23
+ */
24
+ addMany(entries) {
25
+ for (const entry of entries) {
26
+ this.add(entry);
27
+ }
28
+ }
29
+ /**
30
+ * Get logs with optional filtering.
31
+ */
32
+ get(filter) {
33
+ let result = [...this.logs];
34
+ if (filter?.types && filter.types.length > 0) {
35
+ result = result.filter(log => filter.types.includes(log.type));
36
+ }
37
+ if (filter?.since) {
38
+ const sinceDate = new Date(filter.since);
39
+ result = result.filter(log => new Date(log.timestamp) >= sinceDate);
40
+ }
41
+ if (filter?.issuer) {
42
+ const issuerLower = filter.issuer.toLowerCase();
43
+ result = result.filter(log => log.issuer?.toLowerCase().includes(issuerLower));
44
+ }
45
+ if (filter?.search) {
46
+ const searchLower = filter.search.toLowerCase();
47
+ result = result.filter(log => log.message.toLowerCase().includes(searchLower) ||
48
+ log.file?.toLowerCase().includes(searchLower) ||
49
+ log.request?.toLowerCase().includes(searchLower));
50
+ }
51
+ if (filter?.limit && filter.limit > 0) {
52
+ // Return most recent logs
53
+ result = result.slice(-filter.limit);
54
+ }
55
+ return result;
56
+ }
57
+ /**
58
+ * Get only errors and warnings.
59
+ */
60
+ getErrors(limit) {
61
+ return this.get({
62
+ types: ['error', 'warn'],
63
+ limit,
64
+ });
65
+ }
66
+ /**
67
+ * Count logs by type.
68
+ */
69
+ countByType(type) {
70
+ return this.logs.filter(log => log.type === type).length;
71
+ }
72
+ /**
73
+ * Get total log count.
74
+ */
75
+ get count() {
76
+ return this.logs.length;
77
+ }
78
+ /**
79
+ * Get the timestamp of the most recent log.
80
+ */
81
+ get lastTimestamp() {
82
+ if (this.logs.length === 0)
83
+ return null;
84
+ return this.logs[this.logs.length - 1].timestamp;
85
+ }
86
+ /**
87
+ * Clear all logs from the store.
88
+ */
89
+ clear() {
90
+ this.logs = [];
91
+ }
92
+ }
93
+ //# sourceMappingURL=log-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-store.js","sourceRoot":"","sources":["../src/log-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import { LogStore } from './log-store.js';
2
+ /**
3
+ * Watches a Re.Pack log file and streams entries to a LogStore.
4
+ */
5
+ export declare class LogWatcher {
6
+ private filePath;
7
+ private store;
8
+ private watcher;
9
+ private lastPosition;
10
+ private watching;
11
+ constructor(filePath: string, store: LogStore);
12
+ /**
13
+ * Start watching the log file.
14
+ */
15
+ start(): Promise<void>;
16
+ /**
17
+ * Stop watching the log file.
18
+ */
19
+ stop(): Promise<void>;
20
+ /**
21
+ * Read new content from the log file since last position.
22
+ */
23
+ private readNewContent;
24
+ /**
25
+ * Parse a single log line into a LogEntry.
26
+ */
27
+ private parseLine;
28
+ /**
29
+ * Normalize various log level formats to our LogType.
30
+ */
31
+ private normalizeType;
32
+ /**
33
+ * Check if the watcher is currently active.
34
+ */
35
+ get isWatching(): boolean;
36
+ /**
37
+ * Check if the log file exists.
38
+ */
39
+ get fileExists(): boolean;
40
+ /**
41
+ * Get the path being watched.
42
+ */
43
+ get path(): string;
44
+ }
45
+ //# sourceMappingURL=log-watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-watcher.d.ts","sourceRoot":"","sources":["../src/log-watcher.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,YAAY,CAAa;IACjC,OAAO,CAAC,QAAQ,CAAkB;gBAEtB,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ;IAK7C;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAkC5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B;;OAEG;YACW,cAAc;IAwC5B;;OAEG;IACH,OAAO,CAAC,SAAS;IA0BjB;;OAEG;IACH,OAAO,CAAC,aAAa;IAqBrB;;OAEG;IACH,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}