@treedy/pyright-mcp 1.0.0 → 1.1.1

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.
@@ -1,9 +1,9 @@
1
1
  import { z } from 'zod';
2
2
  export declare const diagnosticsSchema: {
3
- file: z.ZodString;
3
+ path: z.ZodString;
4
4
  };
5
5
  export declare function diagnostics(args: {
6
- file: string;
6
+ path: string;
7
7
  }): Promise<{
8
8
  content: {
9
9
  type: "text";
@@ -1,35 +1,93 @@
1
1
  import { z } from 'zod';
2
- import { getLspClient } from '../lsp-client.js';
3
- import { fromPosition } from '../utils/position.js';
4
- import { DiagnosticSeverity } from 'vscode-languageserver-protocol';
2
+ import { execSync } from 'child_process';
3
+ import { findProjectRoot } from '../utils/position.js';
5
4
  export const diagnosticsSchema = {
6
- file: z.string().describe('Absolute path to the Python file'),
7
- };
8
- const severityNames = {
9
- [DiagnosticSeverity.Error]: 'Error',
10
- [DiagnosticSeverity.Warning]: 'Warning',
11
- [DiagnosticSeverity.Information]: 'Information',
12
- [DiagnosticSeverity.Hint]: 'Hint',
5
+ path: z
6
+ .string()
7
+ .describe('Path to a Python file or directory to check'),
13
8
  };
14
9
  export async function diagnostics(args) {
15
- const client = getLspClient();
16
- const result = await client.getDiagnostics(args.file);
17
- if (result.length === 0) {
10
+ const { path } = args;
11
+ // Determine project root from path
12
+ const projectRoot = findProjectRoot(path);
13
+ // Build pyright command - path can be file or directory
14
+ const target = path;
15
+ const cmd = `pyright "${target}" --outputjson`;
16
+ let output;
17
+ try {
18
+ const result = execSync(cmd, {
19
+ encoding: 'utf-8',
20
+ cwd: projectRoot,
21
+ timeout: 60000,
22
+ maxBuffer: 10 * 1024 * 1024,
23
+ });
24
+ output = JSON.parse(result);
25
+ }
26
+ catch (e) {
27
+ const error = e;
28
+ // pyright returns non-zero exit code if there are errors
29
+ if (error.stdout) {
30
+ try {
31
+ output = JSON.parse(error.stdout);
32
+ }
33
+ catch {
34
+ return {
35
+ content: [
36
+ {
37
+ type: 'text',
38
+ text: `Error running pyright: ${error.message || 'Unknown error'}`,
39
+ },
40
+ ],
41
+ };
42
+ }
43
+ }
44
+ else {
45
+ return {
46
+ content: [
47
+ {
48
+ type: 'text',
49
+ text: `Error running pyright: ${error.message || 'Unknown error'}\n\nMake sure pyright is installed: npm install -g pyright`,
50
+ },
51
+ ],
52
+ };
53
+ }
54
+ }
55
+ const diags = output.generalDiagnostics || [];
56
+ const summary = output.summary;
57
+ if (diags.length === 0) {
58
+ let text = `**No issues found**\n\n`;
59
+ text += `- Files analyzed: ${summary.filesAnalyzed}\n`;
60
+ text += `- Time: ${summary.timeInSec}s`;
18
61
  return {
19
- content: [{ type: 'text', text: `No diagnostics for ${args.file}` }],
62
+ content: [{ type: 'text', text }],
20
63
  };
21
64
  }
22
- let output = `**Diagnostics** for ${args.file}\n\n`;
23
- output += `Found ${result.length} issue(s):\n\n`;
24
- for (const diag of result) {
25
- const pos = fromPosition(diag.range.start);
26
- const severity = diag.severity ? severityNames[diag.severity] || 'Unknown' : 'Unknown';
27
- const source = diag.source ? `[${diag.source}] ` : '';
28
- const code = diag.code ? ` (${diag.code})` : '';
29
- output += `- **${severity}** at line ${pos.line}:${pos.column}${code}\n`;
30
- output += ` ${source}${diag.message}\n\n`;
65
+ // Group by file
66
+ const byFile = new Map();
67
+ for (const diag of diags) {
68
+ const list = byFile.get(diag.file) || [];
69
+ list.push(diag);
70
+ byFile.set(diag.file, list);
71
+ }
72
+ let text = `**Diagnostics Summary**\n\n`;
73
+ text += `- Errors: ${summary.errorCount}\n`;
74
+ text += `- Warnings: ${summary.warningCount}\n`;
75
+ text += `- Information: ${summary.informationCount}\n`;
76
+ text += `- Files analyzed: ${summary.filesAnalyzed}\n`;
77
+ text += `- Time: ${summary.timeInSec}s\n\n`;
78
+ text += `---\n\n`;
79
+ for (const [filePath, fileDiags] of byFile) {
80
+ text += `### ${filePath}\n\n`;
81
+ for (const diag of fileDiags) {
82
+ const line = diag.range.start.line + 1;
83
+ const col = diag.range.start.character + 1;
84
+ const rule = diag.rule ? ` (${diag.rule})` : '';
85
+ const icon = diag.severity === 'error' ? '❌' : diag.severity === 'warning' ? '⚠️' : 'ℹ️';
86
+ text += `- ${icon} **${diag.severity}** at ${line}:${col}${rule}\n`;
87
+ text += ` ${diag.message}\n\n`;
88
+ }
31
89
  }
32
90
  return {
33
- content: [{ type: 'text', text: output }],
91
+ content: [{ type: 'text', text }],
34
92
  };
35
93
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@treedy/pyright-mcp",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "MCP server exposing Pyright LSP features for Python code intelligence",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",