@zachsents/ts-mcp 0.3.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,170 @@
1
+ # TS Hover MCP
2
+
3
+ **Give AI agents TypeScript type inference — no editor required.**
4
+
5
+ A standalone MCP server that provides TypeScript type information using [tsgo](https://github.com/nicolo-ribaudo/tc39-proposal-type-annotations) (the native Go-based TypeScript compiler). Works with any MCP client — Cursor, Claude Desktop, VS Code, Windsurf, or any other agent.
6
+
7
+ No running editor needed. It spawns and manages tsgo LSP instances directly, keeping them warm for fast subsequent queries.
8
+
9
+ ## Prerequisites
10
+
11
+ Install tsgo globally:
12
+
13
+ ```bash
14
+ bun add -g @typescript/native-preview
15
+ ```
16
+
17
+ ## Install
18
+
19
+ ### Cursor
20
+
21
+ [![Install in Cursor](https://img.shields.io/badge/Install_in-Cursor-blue?logo=cursor&logoColor=white)](cursor://anysphere.cursor-deeplink/mcp/install?name=ts-hover&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkB6YWNoc2VudHMvdHMtbWNwIl19)
22
+
23
+ Or manually add to `.cursor/mcp.json`:
24
+
25
+ ```json
26
+ {
27
+ "mcpServers": {
28
+ "ts-hover": {
29
+ "command": "npx",
30
+ "args": ["-y", "@zachsents/ts-mcp"]
31
+ }
32
+ }
33
+ }
34
+ ```
35
+
36
+ ### VS Code
37
+
38
+ [![Install in VS Code](https://img.shields.io/badge/Install_in-VS_Code-blue?logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=ts-hover&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40zachsents%2Fts-mcp%22%5D%7D) [![Install in VS Code Insiders](https://img.shields.io/badge/Install_in-VS_Code_Insiders-teal?logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=ts-hover&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40zachsents%2Fts-mcp%22%5D%7D&quality=insiders)
39
+
40
+ Or manually add to your User Settings (JSON):
41
+
42
+ ```json
43
+ {
44
+ "mcp": {
45
+ "servers": {
46
+ "ts-hover": {
47
+ "command": "npx",
48
+ "args": ["-y", "@zachsents/ts-mcp"]
49
+ }
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ ### Claude Desktop
56
+
57
+ Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
58
+
59
+ ```json
60
+ {
61
+ "mcpServers": {
62
+ "ts-hover": {
63
+ "command": "npx",
64
+ "args": ["-y", "@zachsents/ts-mcp"]
65
+ }
66
+ }
67
+ }
68
+ ```
69
+
70
+ ### Claude Code
71
+
72
+ ```bash
73
+ claude mcp add-json ts-hover '{"command":"npx","args":["-y","@zachsents/ts-mcp"]}'
74
+ ```
75
+
76
+ ### Windsurf
77
+
78
+ Add to your Windsurf MCP config:
79
+
80
+ ```json
81
+ {
82
+ "mcpServers": {
83
+ "ts-hover": {
84
+ "command": "npx",
85
+ "args": ["-y", "@zachsents/ts-mcp"]
86
+ }
87
+ }
88
+ }
89
+ ```
90
+
91
+ ## How it works
92
+
93
+ 1. Agent calls a tool (e.g. `hover` with a file path and position)
94
+ 2. The MCP server finds the nearest `tsconfig.json` to determine the project root
95
+ 3. It spawns (or reuses) a tsgo LSP instance for that project
96
+ 4. Returns the type information
97
+ 5. The tsgo instance stays warm for 5 minutes, making follow-up queries near-instant
98
+
99
+ Multiple project roots are handled automatically — each gets its own tsgo instance.
100
+
101
+ ## Tools
102
+
103
+ ### `hover`
104
+
105
+ Get TypeScript type information at a position, plus where it's defined. Returns the same info you'd see hovering in an IDE — resolved types, inferred types, JSDoc — and the definition location.
106
+
107
+ | Parameter | Type | Description |
108
+ | ----------- | -------- | ------------------------------------ |
109
+ | `file` | `string` | Absolute path to the TypeScript file |
110
+ | `line` | `number` | Line number (0-indexed) |
111
+ | `character` | `number` | Character position (0-indexed) |
112
+
113
+ ### `diagnostics`
114
+
115
+ Get TypeScript errors and warnings for a file, along with available quick fixes and their exact text edits.
116
+
117
+ | Parameter | Type | Description |
118
+ | --------- | -------- | ------------------------------------ |
119
+ | `file` | `string` | Absolute path to the TypeScript file |
120
+
121
+ ### `references`
122
+
123
+ Find all references to a symbol across the project.
124
+
125
+ | Parameter | Type | Description |
126
+ | ----------- | -------- | ------------------------------------ |
127
+ | `file` | `string` | Absolute path to the TypeScript file |
128
+ | `line` | `number` | Line number (0-indexed) |
129
+ | `character` | `number` | Character position (0-indexed) |
130
+
131
+ ### `outline`
132
+
133
+ Get a structured outline of all symbols in a file — functions, classes, interfaces, types, variables — with line numbers and nesting.
134
+
135
+ | Parameter | Type | Description |
136
+ | --------- | -------- | ------------------------------------ |
137
+ | `file` | `string` | Absolute path to the TypeScript file |
138
+
139
+ ### `rename`
140
+
141
+ Rename a symbol across the project. Returns the exact text edits needed in each file.
142
+
143
+ | Parameter | Type | Description |
144
+ | ----------- | -------- | ------------------------------------ |
145
+ | `file` | `string` | Absolute path to the TypeScript file |
146
+ | `line` | `number` | Line number (0-indexed) |
147
+ | `character` | `number` | Character position (0-indexed) |
148
+ | `newName` | `string` | The new name for the symbol |
149
+
150
+ ### `inlay_hints`
151
+
152
+ Get inferred type annotations for a line range — variable types, parameter types, return types that TypeScript infers but aren't written in code.
153
+
154
+ | Parameter | Type | Description |
155
+ | ----------- | -------- | ------------------------------------ |
156
+ | `file` | `string` | Absolute path to the TypeScript file |
157
+ | `startLine` | `number` | Start line (0-indexed, inclusive) |
158
+ | `endLine` | `number` | End line (0-indexed, exclusive) |
159
+
160
+ > **Note:** Requires tsgo inlay hint support, which is still in development. The tool will start returning results as tsgo fills in this capability.
161
+
162
+ ## Configuration
163
+
164
+ | Env var | Description |
165
+ | ----------- | ------------------------------------ |
166
+ | `TSGO_PATH` | Override the path to the tsgo binary |
167
+
168
+ ## License
169
+
170
+ MIT — Zach Sents
package/dist/index.js ADDED
@@ -0,0 +1,220 @@
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 { TsgoPool } from "./pool.js";
6
+ import { resolveTsgoBinary } from "./resolve-binary.js";
7
+ const binaryPath = resolveTsgoBinary();
8
+ const pool = new TsgoPool(binaryPath);
9
+ const server = new McpServer({
10
+ name: "ts-hover",
11
+ version: "0.3.0",
12
+ });
13
+ server.registerTool("hover", {
14
+ title: "TypeScript Hover",
15
+ description: "Get TypeScript type information at a position, plus where it's defined. Returns the same info you'd see hovering in an IDE — resolved types, inferred types, JSDoc — and the definition location.",
16
+ inputSchema: {
17
+ file: z
18
+ .string()
19
+ .describe("Absolute path to the TypeScript/JavaScript file"),
20
+ line: z.number().describe("Line number (0-indexed)"),
21
+ character: z.number().describe("Character position (0-indexed)"),
22
+ },
23
+ }, async ({ file, line, character }) => {
24
+ const { hover, definition } = await pool.hoverWithDefinition(file, line, character);
25
+ const parts = [];
26
+ if (hover)
27
+ parts.push(hover);
28
+ if (definition) {
29
+ parts.push(`Defined at: ${definition.file}:${definition.line}:${definition.character}`);
30
+ }
31
+ return {
32
+ content: [
33
+ {
34
+ type: "text",
35
+ text: parts.length > 0 ? parts.join("\n\n") : "(no hover info)",
36
+ },
37
+ ],
38
+ };
39
+ });
40
+ server.registerTool("diagnostics", {
41
+ title: "TypeScript Diagnostics",
42
+ description: "Get TypeScript errors and warnings for a file, along with available quick fixes and their exact text edits. Use this after editing a file to check for type errors.",
43
+ inputSchema: {
44
+ file: z
45
+ .string()
46
+ .describe("Absolute path to the TypeScript/JavaScript file"),
47
+ },
48
+ }, async ({ file }) => {
49
+ const { diagnostics, actions } = await pool.diagnosticsWithFixes(file);
50
+ if (diagnostics.length === 0 && actions.length === 0) {
51
+ return {
52
+ content: [{ type: "text", text: "No errors or warnings." }],
53
+ };
54
+ }
55
+ const parts = [];
56
+ for (const d of diagnostics) {
57
+ const code = d.code != null ? ` TS${d.code}` : "";
58
+ parts.push(`${d.line}:${d.character} ${d.severity}${code}: ${d.message}`);
59
+ }
60
+ const fixes = actions.filter((a) => a.kind?.startsWith("quickfix"));
61
+ const sourceActions = actions.filter((a) => a.kind?.startsWith("source"));
62
+ if (fixes.length > 0) {
63
+ parts.push("");
64
+ parts.push("Quick fixes:");
65
+ for (const fix of fixes) {
66
+ parts.push(` ${fix.title}`);
67
+ for (const edit of fix.edits) {
68
+ parts.push(formatTextEdit(edit));
69
+ }
70
+ }
71
+ }
72
+ if (sourceActions.length > 0) {
73
+ parts.push("");
74
+ parts.push("Source actions:");
75
+ for (const action of sourceActions) {
76
+ parts.push(` ${action.title}`);
77
+ for (const edit of action.edits) {
78
+ parts.push(formatTextEdit(edit));
79
+ }
80
+ }
81
+ }
82
+ return {
83
+ content: [{ type: "text", text: parts.join("\n") }],
84
+ };
85
+ });
86
+ server.registerTool("references", {
87
+ title: "TypeScript References",
88
+ description: "Find all references to a symbol across the project. Returns a list of file locations where the symbol is used.",
89
+ inputSchema: {
90
+ file: z
91
+ .string()
92
+ .describe("Absolute path to the TypeScript/JavaScript file"),
93
+ line: z.number().describe("Line number (0-indexed)"),
94
+ character: z.number().describe("Character position (0-indexed)"),
95
+ },
96
+ }, async ({ file, line, character }) => {
97
+ const locations = await pool.references(file, line, character);
98
+ if (locations.length === 0) {
99
+ return {
100
+ content: [{ type: "text", text: "No references found." }],
101
+ };
102
+ }
103
+ const text = locations
104
+ .map((loc) => `${loc.file}:${loc.line}:${loc.character}`)
105
+ .join("\n");
106
+ return {
107
+ content: [{ type: "text", text }],
108
+ };
109
+ });
110
+ server.registerTool("outline", {
111
+ title: "TypeScript Outline",
112
+ description: "Get a structured outline of all symbols in a file — functions, classes, interfaces, types, variables, etc. with their line numbers. Useful for understanding what's in a file without reading it.",
113
+ inputSchema: {
114
+ file: z
115
+ .string()
116
+ .describe("Absolute path to the TypeScript/JavaScript file"),
117
+ },
118
+ }, async ({ file }) => {
119
+ const symbols = await pool.outline(file);
120
+ if (symbols.length === 0) {
121
+ return {
122
+ content: [{ type: "text", text: "No symbols found." }],
123
+ };
124
+ }
125
+ const lines = [];
126
+ formatSymbolTree(symbols, lines, 0);
127
+ return {
128
+ content: [{ type: "text", text: lines.join("\n") }],
129
+ };
130
+ });
131
+ server.registerTool("rename", {
132
+ title: "TypeScript Rename",
133
+ description: "Rename a symbol across the project. Returns the exact text edits needed in each file. Use this instead of manually find-and-replace to ensure type-safe renames.",
134
+ inputSchema: {
135
+ file: z
136
+ .string()
137
+ .describe("Absolute path to the TypeScript/JavaScript file"),
138
+ line: z.number().describe("Line number (0-indexed)"),
139
+ character: z.number().describe("Character position (0-indexed)"),
140
+ newName: z.string().describe("The new name for the symbol"),
141
+ },
142
+ }, async ({ file, line, character, newName }) => {
143
+ const edits = await pool.rename(file, line, character, newName);
144
+ if (edits.length === 0) {
145
+ return {
146
+ content: [{ type: "text", text: "No rename edits." }],
147
+ };
148
+ }
149
+ const byFile = new Map();
150
+ for (const edit of edits) {
151
+ const group = byFile.get(edit.file) ?? [];
152
+ group.push(edit);
153
+ byFile.set(edit.file, group);
154
+ }
155
+ const parts = [];
156
+ for (const [filePath, fileEdits] of byFile) {
157
+ parts.push(`${filePath}:`);
158
+ for (const e of fileEdits) {
159
+ parts.push(` ${e.startLine}:${e.startCharacter} -> ${e.endLine}:${e.endCharacter}: ${newName}`);
160
+ }
161
+ }
162
+ return {
163
+ content: [{ type: "text", text: parts.join("\n") }],
164
+ };
165
+ });
166
+ server.registerTool("inlay_hints", {
167
+ title: "TypeScript Inlay Hints",
168
+ description: "Get inferred type annotations for a line range — variable types, parameter types, return types that TypeScript infers but aren't written in code. Useful for understanding what types TS has inferred.",
169
+ inputSchema: {
170
+ file: z
171
+ .string()
172
+ .describe("Absolute path to the TypeScript/JavaScript file"),
173
+ startLine: z.number().describe("Start line (0-indexed, inclusive)"),
174
+ endLine: z.number().describe("End line (0-indexed, exclusive)"),
175
+ },
176
+ }, async ({ file, startLine, endLine }) => {
177
+ const hints = await pool.inlayHints(file, startLine, endLine);
178
+ if (hints.length === 0) {
179
+ return {
180
+ content: [{ type: "text", text: "No inlay hints." }],
181
+ };
182
+ }
183
+ const text = hints
184
+ .map((h) => `${h.line}:${h.character} ${h.kind}: ${h.text}`)
185
+ .join("\n");
186
+ return {
187
+ content: [{ type: "text", text }],
188
+ };
189
+ });
190
+ /** Recursively format a symbol tree with indentation */
191
+ function formatSymbolTree(symbols, lines, depth) {
192
+ const indent = " ".repeat(depth);
193
+ for (const sym of symbols) {
194
+ lines.push(`${indent}${sym.kind} ${sym.name} (line ${sym.line})`);
195
+ if (sym.children.length > 0) {
196
+ formatSymbolTree(sym.children, lines, depth + 1);
197
+ }
198
+ }
199
+ }
200
+ function formatTextEdit(edit) {
201
+ const loc = ` ${edit.file}:${edit.startLine}:${edit.startCharacter}`;
202
+ if (edit.newText === "") {
203
+ return `${loc} (delete to ${edit.endLine}:${edit.endCharacter})`;
204
+ }
205
+ const preview = edit.newText.includes("\n")
206
+ ? edit.newText.split("\n")[0] + "..."
207
+ : edit.newText;
208
+ if (edit.startLine === edit.endLine &&
209
+ edit.startCharacter === edit.endCharacter) {
210
+ return `${loc} (insert: ${preview})`;
211
+ }
212
+ return `${loc} (replace to ${edit.endLine}:${edit.endCharacter}: ${preview})`;
213
+ }
214
+ process.on("SIGINT", async () => {
215
+ await pool.shutdown();
216
+ process.exit(0);
217
+ });
218
+ const transport = new StdioServerTransport();
219
+ await server.connect(transport);
220
+ //# 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,556 @@
1
+ import { spawn } from "node:child_process";
2
+ import { readFile } from "node:fs/promises";
3
+ import { extname } from "node:path";
4
+ import { z } from "zod";
5
+ const REQUEST_TIMEOUT_MS = 30_000;
6
+ const jsonRpcMessageSchema = z.object({
7
+ jsonrpc: z.literal("2.0"),
8
+ id: z.union([z.number(), z.string()]).optional(),
9
+ method: z.string().optional(),
10
+ params: z.unknown().optional(),
11
+ result: z.unknown().optional(),
12
+ error: z
13
+ .object({
14
+ code: z.number(),
15
+ message: z.string(),
16
+ data: z.unknown().optional(),
17
+ })
18
+ .optional(),
19
+ });
20
+ const hoverResultSchema = z.object({
21
+ contents: z.unknown(),
22
+ });
23
+ /** MarkupContent shape: `{ kind, value }` or just a raw `{ value }` string */
24
+ const markupContentSchema = z.object({ value: z.string() });
25
+ // Shared LSP building blocks
26
+ const positionSchema = z.object({ line: z.number(), character: z.number() });
27
+ const rangeSchema = z.object({ start: positionSchema, end: positionSchema });
28
+ // Definition/references response — can be Location or LocationLink
29
+ const locationSchema = z.object({ uri: z.string(), range: rangeSchema });
30
+ const locationLinkSchema = z.object({
31
+ targetUri: z.string(),
32
+ targetRange: rangeSchema,
33
+ targetSelectionRange: rangeSchema.optional(),
34
+ });
35
+ // Diagnostics
36
+ const diagnosticItemSchema = z.object({
37
+ range: rangeSchema,
38
+ severity: z.number().optional(),
39
+ code: z.union([z.number(), z.string()]).optional(),
40
+ source: z.string().optional(),
41
+ message: z.string(),
42
+ });
43
+ const diagnosticResultSchema = z.object({
44
+ kind: z.string(),
45
+ items: z.array(diagnosticItemSchema),
46
+ });
47
+ // Code actions
48
+ const textEditSchema = z.object({ range: rangeSchema, newText: z.string() });
49
+ const codeActionSchema = z.object({
50
+ title: z.string(),
51
+ kind: z.string().optional(),
52
+ diagnostics: z.array(diagnosticItemSchema).optional(),
53
+ edit: z
54
+ .object({
55
+ changes: z.record(z.string(), z.array(textEditSchema)).optional(),
56
+ })
57
+ .optional(),
58
+ });
59
+ const SEVERITY_LABELS = ["", "error", "warning", "info", "hint"];
60
+ // Document symbols — tsgo returns flat SymbolInformation[], not hierarchical
61
+ const symbolInformationSchema = z.object({
62
+ name: z.string(),
63
+ kind: z.number(),
64
+ containerName: z.string().optional(),
65
+ location: locationSchema,
66
+ });
67
+ const SYMBOL_KIND_LABELS = {
68
+ 1: "file",
69
+ 2: "module",
70
+ 3: "namespace",
71
+ 5: "class",
72
+ 6: "method",
73
+ 7: "property",
74
+ 8: "field",
75
+ 9: "constructor",
76
+ 10: "enum",
77
+ 11: "interface",
78
+ 12: "function",
79
+ 13: "variable",
80
+ 14: "constant",
81
+ 22: "enum member",
82
+ 26: "type parameter",
83
+ };
84
+ // Workspace edit (shared by rename and code actions)
85
+ const workspaceEditSchema = z.object({
86
+ changes: z.record(z.string(), z.array(textEditSchema)).optional(),
87
+ });
88
+ // Inlay hints
89
+ const inlayHintLabelSchema = z.union([
90
+ z.string(),
91
+ z.array(z.object({ value: z.string() })),
92
+ ]);
93
+ const inlayHintSchema = z.object({
94
+ position: positionSchema,
95
+ label: inlayHintLabelSchema,
96
+ kind: z.number().optional(),
97
+ });
98
+ const INLAY_HINT_KIND_LABELS = {
99
+ 1: "type",
100
+ 2: "parameter",
101
+ };
102
+ /**
103
+ * LSP JSON-RPC client that communicates with a tsgo process over stdio. Handles
104
+ * Content-Length message framing, request/response correlation,
105
+ * server-initiated requests (e.g. client/registerCapability), and automatic
106
+ * document open/change tracking.
107
+ */
108
+ export class LspClient {
109
+ rootUri;
110
+ proc;
111
+ stdin;
112
+ nextId = 1;
113
+ pending = new Map();
114
+ buffer = Buffer.alloc(0);
115
+ documents = new Map();
116
+ alive = true;
117
+ constructor(binaryPath, rootUri) {
118
+ this.rootUri = rootUri;
119
+ this.proc = spawn(binaryPath, ["--lsp", "--stdio"], {
120
+ stdio: ["pipe", "pipe", "pipe"],
121
+ });
122
+ if (!this.proc.stdin || !this.proc.stdout) {
123
+ throw new Error("Failed to create tsgo process with piped stdio");
124
+ }
125
+ this.stdin = this.proc.stdin;
126
+ this.proc.stdout.on("data", (chunk) => {
127
+ this.buffer = Buffer.concat([this.buffer, chunk]);
128
+ this.drainBuffer();
129
+ });
130
+ this.proc.on("exit", (code) => {
131
+ this.alive = false;
132
+ for (const [, req] of this.pending) {
133
+ req.reject(new Error(`tsgo exited with code ${code}`));
134
+ clearTimeout(req.timer);
135
+ }
136
+ this.pending.clear();
137
+ });
138
+ }
139
+ /** Create and initialize a new LSP client for a project root */
140
+ static async create(binaryPath, rootUri) {
141
+ const client = new LspClient(binaryPath, rootUri);
142
+ await client.initialize();
143
+ return client;
144
+ }
145
+ get isAlive() {
146
+ return this.alive;
147
+ }
148
+ /** Get hover information at a position in a file */
149
+ async hover(filePath, line, character) {
150
+ if (!this.alive)
151
+ throw new Error("LSP client is not alive");
152
+ const uri = pathToUri(filePath);
153
+ await this.ensureDocumentOpen(filePath, uri);
154
+ const result = await this.sendRequest("textDocument/hover", {
155
+ textDocument: { uri },
156
+ position: { line, character },
157
+ });
158
+ const parsed = hoverResultSchema.safeParse(result);
159
+ if (!parsed.success)
160
+ return null;
161
+ return formatHoverContents(parsed.data.contents);
162
+ }
163
+ /** Get definition location(s) for a symbol at a position */
164
+ async definition(filePath, line, character) {
165
+ if (!this.alive)
166
+ throw new Error("LSP client is not alive");
167
+ const uri = pathToUri(filePath);
168
+ await this.ensureDocumentOpen(filePath, uri);
169
+ const result = await this.sendRequest("textDocument/definition", {
170
+ textDocument: { uri },
171
+ position: { line, character },
172
+ });
173
+ return parseLocations(result);
174
+ }
175
+ /** Pull diagnostics for a file */
176
+ async diagnostics(filePath) {
177
+ if (!this.alive)
178
+ throw new Error("LSP client is not alive");
179
+ const uri = pathToUri(filePath);
180
+ await this.ensureDocumentOpen(filePath, uri);
181
+ const result = await this.sendRequest("textDocument/diagnostic", {
182
+ textDocument: { uri },
183
+ });
184
+ const parsed = diagnosticResultSchema.safeParse(result);
185
+ if (!parsed.success)
186
+ return [];
187
+ return parsed.data.items.map((item) => ({
188
+ line: item.range.start.line,
189
+ character: item.range.start.character,
190
+ endLine: item.range.end.line,
191
+ endCharacter: item.range.end.character,
192
+ severity: SEVERITY_LABELS[item.severity ?? 1] ?? "error",
193
+ message: item.message,
194
+ code: item.code,
195
+ }));
196
+ }
197
+ /** Get code actions for a range, optionally scoped to specific diagnostics */
198
+ async codeActions(filePath, range, diagnostics = []) {
199
+ if (!this.alive)
200
+ throw new Error("LSP client is not alive");
201
+ const uri = pathToUri(filePath);
202
+ await this.ensureDocumentOpen(filePath, uri);
203
+ const lspDiagnostics = diagnostics.map((d) => ({
204
+ range: {
205
+ start: { line: d.line, character: d.character },
206
+ end: { line: d.endLine, character: d.endCharacter },
207
+ },
208
+ severity: SEVERITY_LABELS.indexOf(d.severity) || 1,
209
+ message: d.message,
210
+ ...(d.code != null ? { code: d.code } : {}),
211
+ }));
212
+ const result = await this.sendRequest("textDocument/codeAction", {
213
+ textDocument: { uri },
214
+ range,
215
+ context: { diagnostics: lspDiagnostics },
216
+ });
217
+ if (!Array.isArray(result))
218
+ return [];
219
+ const actions = [];
220
+ for (const item of result) {
221
+ const parsed = codeActionSchema.safeParse(item);
222
+ if (!parsed.success || !parsed.data.edit)
223
+ continue;
224
+ actions.push({
225
+ title: parsed.data.title,
226
+ kind: parsed.data.kind,
227
+ edits: parseWorkspaceEdit(parsed.data.edit),
228
+ });
229
+ }
230
+ return actions;
231
+ }
232
+ /** Get a structured outline of all symbols in a file */
233
+ async documentSymbols(filePath) {
234
+ if (!this.alive)
235
+ throw new Error("LSP client is not alive");
236
+ const uri = pathToUri(filePath);
237
+ await this.ensureDocumentOpen(filePath, uri);
238
+ const result = await this.sendRequest("textDocument/documentSymbol", { textDocument: { uri } });
239
+ if (!Array.isArray(result))
240
+ return [];
241
+ return buildSymbolTree(result);
242
+ }
243
+ /** Rename a symbol across the project */
244
+ async rename(filePath, line, character, newName) {
245
+ if (!this.alive)
246
+ throw new Error("LSP client is not alive");
247
+ const uri = pathToUri(filePath);
248
+ await this.ensureDocumentOpen(filePath, uri);
249
+ const result = await this.sendRequest("textDocument/rename", {
250
+ textDocument: { uri },
251
+ position: { line, character },
252
+ newName,
253
+ });
254
+ return parseWorkspaceEdit(result);
255
+ }
256
+ /** Get inferred type annotations for a line range */
257
+ async inlayHints(filePath, startLine, endLine) {
258
+ if (!this.alive)
259
+ throw new Error("LSP client is not alive");
260
+ const uri = pathToUri(filePath);
261
+ await this.ensureDocumentOpen(filePath, uri);
262
+ const result = await this.sendRequest("textDocument/inlayHint", {
263
+ textDocument: { uri },
264
+ range: {
265
+ start: { line: startLine, character: 0 },
266
+ end: { line: endLine, character: 0 },
267
+ },
268
+ });
269
+ if (!Array.isArray(result))
270
+ return [];
271
+ const hints = [];
272
+ for (const item of result) {
273
+ const parsed = inlayHintSchema.safeParse(item);
274
+ if (!parsed.success)
275
+ continue;
276
+ const label = parsed.data.label;
277
+ const text = typeof label === "string"
278
+ ? label
279
+ : label.map((part) => part.value).join("");
280
+ hints.push({
281
+ line: parsed.data.position.line,
282
+ character: parsed.data.position.character,
283
+ text,
284
+ kind: INLAY_HINT_KIND_LABELS[parsed.data.kind ?? 0] ?? "unknown",
285
+ });
286
+ }
287
+ return hints;
288
+ }
289
+ /** Find all references to a symbol at a position */
290
+ async references(filePath, line, character) {
291
+ if (!this.alive)
292
+ throw new Error("LSP client is not alive");
293
+ const uri = pathToUri(filePath);
294
+ await this.ensureDocumentOpen(filePath, uri);
295
+ const result = await this.sendRequest("textDocument/references", {
296
+ textDocument: { uri },
297
+ position: { line, character },
298
+ context: { includeDeclaration: true },
299
+ });
300
+ return parseLocations(result);
301
+ }
302
+ /** Gracefully shut down the LSP server */
303
+ async shutdown() {
304
+ if (!this.alive)
305
+ return;
306
+ this.alive = false;
307
+ try {
308
+ await this.sendRequest("shutdown", null);
309
+ this.sendNotification("exit", undefined);
310
+ }
311
+ catch {
312
+ // Process may already be dead
313
+ }
314
+ this.proc.kill();
315
+ }
316
+ async initialize() {
317
+ await this.sendRequest("initialize", {
318
+ processId: process.pid,
319
+ rootUri: this.rootUri,
320
+ capabilities: {
321
+ textDocument: {
322
+ hover: { contentFormat: ["markdown", "plaintext"] },
323
+ },
324
+ },
325
+ });
326
+ this.sendNotification("initialized", {});
327
+ }
328
+ /** Open a document in the LSP if needed, or update it if contents changed */
329
+ async ensureDocumentOpen(filePath, uri) {
330
+ const content = await readFile(filePath, "utf-8");
331
+ const existing = this.documents.get(uri);
332
+ if (!existing) {
333
+ this.sendNotification("textDocument/didOpen", {
334
+ textDocument: {
335
+ uri,
336
+ languageId: getLanguageId(filePath),
337
+ version: 1,
338
+ text: content,
339
+ },
340
+ });
341
+ this.documents.set(uri, { version: 1, content });
342
+ return;
343
+ }
344
+ if (existing.content !== content) {
345
+ const version = existing.version + 1;
346
+ this.sendNotification("textDocument/didChange", {
347
+ textDocument: { uri, version },
348
+ contentChanges: [{ text: content }],
349
+ });
350
+ this.documents.set(uri, { version, content });
351
+ }
352
+ }
353
+ sendRequest(method, params) {
354
+ return new Promise((resolve, reject) => {
355
+ const id = this.nextId++;
356
+ const timer = setTimeout(() => {
357
+ this.pending.delete(id);
358
+ reject(new Error(`Request "${method}" timed out after ${REQUEST_TIMEOUT_MS}ms`));
359
+ }, REQUEST_TIMEOUT_MS);
360
+ this.pending.set(id, { resolve, reject, timer });
361
+ this.send({ jsonrpc: "2.0", id, method, params });
362
+ });
363
+ }
364
+ sendNotification(method, params) {
365
+ this.send({ jsonrpc: "2.0", method, params });
366
+ }
367
+ sendResponse(id, result) {
368
+ this.send({ jsonrpc: "2.0", id, result });
369
+ }
370
+ send(message) {
371
+ const body = JSON.stringify(message);
372
+ const header = `Content-Length: ${Buffer.byteLength(body)}\r\n\r\n`;
373
+ this.stdin.write(header + body);
374
+ }
375
+ /** Parse Content-Length framed messages from the buffer */
376
+ drainBuffer() {
377
+ for (;;) {
378
+ const headerEnd = this.buffer.indexOf("\r\n\r\n");
379
+ if (headerEnd === -1)
380
+ return;
381
+ const header = this.buffer.subarray(0, headerEnd).toString("ascii");
382
+ const match = header.match(/Content-Length:\s*(\d+)/);
383
+ if (!match) {
384
+ this.buffer = this.buffer.subarray(headerEnd + 4);
385
+ continue;
386
+ }
387
+ const contentLength = Number.parseInt(match[1] ?? "0", 10);
388
+ const bodyStart = headerEnd + 4;
389
+ const bodyEnd = bodyStart + contentLength;
390
+ if (this.buffer.length < bodyEnd)
391
+ return;
392
+ const body = this.buffer.subarray(bodyStart, bodyEnd).toString("utf-8");
393
+ this.buffer = this.buffer.subarray(bodyEnd);
394
+ const parsed = jsonRpcMessageSchema.safeParse(JSON.parse(body));
395
+ if (parsed.success)
396
+ this.handleMessage(parsed.data);
397
+ }
398
+ }
399
+ handleMessage(message) {
400
+ // Response to one of our requests (numeric id, no method)
401
+ if (typeof message.id === "number" && !message.method) {
402
+ const pending = this.pending.get(message.id);
403
+ if (!pending)
404
+ return;
405
+ clearTimeout(pending.timer);
406
+ this.pending.delete(message.id);
407
+ if (message.error) {
408
+ pending.reject(new Error(`LSP error: ${message.error.message} (${message.error.code})`));
409
+ }
410
+ else {
411
+ pending.resolve(message.result);
412
+ }
413
+ return;
414
+ }
415
+ // Server-initiated request — auto-acknowledge
416
+ if (message.id != null && message.method) {
417
+ this.sendResponse(message.id, null);
418
+ }
419
+ }
420
+ }
421
+ function pathToUri(filePath) {
422
+ return `file://${filePath}`;
423
+ }
424
+ function uriToPath(uri) {
425
+ return uri.replace(/^file:\/\//, "");
426
+ }
427
+ /**
428
+ * Parse Location[] or LocationLink[] from an LSP response into LspLocation[].
429
+ * Handles single objects, arrays, and null.
430
+ */
431
+ function parseLocations(result) {
432
+ if (result == null)
433
+ return [];
434
+ const items = Array.isArray(result) ? result : [result];
435
+ const locations = [];
436
+ for (const item of items) {
437
+ const loc = locationSchema.safeParse(item);
438
+ if (loc.success) {
439
+ locations.push({
440
+ file: uriToPath(loc.data.uri),
441
+ line: loc.data.range.start.line,
442
+ character: loc.data.range.start.character,
443
+ });
444
+ continue;
445
+ }
446
+ const link = locationLinkSchema.safeParse(item);
447
+ if (link.success) {
448
+ const range = link.data.targetSelectionRange ?? link.data.targetRange;
449
+ locations.push({
450
+ file: uriToPath(link.data.targetUri),
451
+ line: range.start.line,
452
+ character: range.start.character,
453
+ });
454
+ }
455
+ }
456
+ return locations;
457
+ }
458
+ /**
459
+ * Build a symbol tree from flat SymbolInformation[]. Uses containerName to
460
+ * reconstruct parent-child relationships.
461
+ */
462
+ function buildSymbolTree(items) {
463
+ const flat = [];
464
+ for (const item of items) {
465
+ const parsed = symbolInformationSchema.safeParse(item);
466
+ if (!parsed.success)
467
+ continue;
468
+ flat.push({
469
+ symbol: {
470
+ name: parsed.data.name,
471
+ kind: SYMBOL_KIND_LABELS[parsed.data.kind] ?? `kind(${parsed.data.kind})`,
472
+ line: parsed.data.location.range.start.line,
473
+ character: parsed.data.location.range.start.character,
474
+ children: [],
475
+ },
476
+ containerName: parsed.data.containerName,
477
+ });
478
+ }
479
+ const byName = new Map();
480
+ for (const entry of flat) {
481
+ if (!byName.has(entry.symbol.name)) {
482
+ byName.set(entry.symbol.name, entry.symbol);
483
+ }
484
+ }
485
+ const roots = [];
486
+ for (const entry of flat) {
487
+ const parent = entry.containerName
488
+ ? byName.get(entry.containerName)
489
+ : undefined;
490
+ if (parent) {
491
+ parent.children.push(entry.symbol);
492
+ }
493
+ else {
494
+ roots.push(entry.symbol);
495
+ }
496
+ }
497
+ return roots;
498
+ }
499
+ /** Parse a WorkspaceEdit into flat LspTextEdit[] */
500
+ function parseWorkspaceEdit(result) {
501
+ const parsed = workspaceEditSchema.safeParse(result);
502
+ if (!parsed.success || !parsed.data.changes)
503
+ return [];
504
+ const edits = [];
505
+ for (const [editUri, textEdits] of Object.entries(parsed.data.changes)) {
506
+ const file = uriToPath(editUri);
507
+ for (const te of textEdits) {
508
+ edits.push({
509
+ file,
510
+ startLine: te.range.start.line,
511
+ startCharacter: te.range.start.character,
512
+ endLine: te.range.end.line,
513
+ endCharacter: te.range.end.character,
514
+ newText: te.newText,
515
+ });
516
+ }
517
+ }
518
+ return edits;
519
+ }
520
+ function getLanguageId(filePath) {
521
+ const ext = extname(filePath);
522
+ switch (ext) {
523
+ case ".ts":
524
+ case ".mts":
525
+ case ".cts":
526
+ return "typescript";
527
+ case ".tsx":
528
+ return "typescriptreact";
529
+ case ".js":
530
+ case ".mjs":
531
+ case ".cjs":
532
+ return "javascript";
533
+ case ".jsx":
534
+ return "javascriptreact";
535
+ default:
536
+ return "typescript";
537
+ }
538
+ }
539
+ /**
540
+ * Extract text from LSP hover contents. Handles MarkupContent (`{ value }`),
541
+ * plain strings, and arrays of either.
542
+ */
543
+ function formatHoverContents(contents) {
544
+ const str = z.string().safeParse(contents);
545
+ if (str.success)
546
+ return str.data;
547
+ if (Array.isArray(contents)) {
548
+ const parts = contents.map(formatHoverContents).filter(Boolean);
549
+ return parts.length > 0 ? parts.join("\n\n") : null;
550
+ }
551
+ const markup = markupContentSchema.safeParse(contents);
552
+ if (markup.success)
553
+ return markup.data.value;
554
+ return null;
555
+ }
556
+ //# sourceMappingURL=lsp-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lsp-client.js","sourceRoot":"","sources":["../src/lsp-client.ts"],"names":[],"mappings":"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"}
package/dist/pool.js ADDED
@@ -0,0 +1,113 @@
1
+ import { existsSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { LspClient, } from "./lsp-client.js";
4
+ const DEFAULT_IDLE_TIMEOUT_MS = 5 * 60 * 1000;
5
+ /**
6
+ * Manages a pool of tsgo LSP instances, one per project root. Automatically
7
+ * discovers the project root from file paths by walking up to the nearest
8
+ * tsconfig.json. Instances are kept warm and shut down after a configurable
9
+ * idle timeout.
10
+ */
11
+ export class TsgoPool {
12
+ binaryPath;
13
+ idleTimeoutMs;
14
+ entries = new Map();
15
+ constructor(binaryPath, idleTimeoutMs = DEFAULT_IDLE_TIMEOUT_MS) {
16
+ this.binaryPath = binaryPath;
17
+ this.idleTimeoutMs = idleTimeoutMs;
18
+ }
19
+ /** Get hover info + definition location in one call */
20
+ async hoverWithDefinition(filePath, line, character) {
21
+ const client = await this.getClient(filePath);
22
+ const [hover, definitions] = await Promise.all([
23
+ client.hover(filePath, line, character),
24
+ client.definition(filePath, line, character),
25
+ ]);
26
+ return { hover, definition: definitions[0] ?? null };
27
+ }
28
+ /** Get diagnostics for a file with available fixes for each error */
29
+ async diagnosticsWithFixes(filePath) {
30
+ const client = await this.getClient(filePath);
31
+ const diagnostics = await client.diagnostics(filePath);
32
+ const actions = await client.codeActions(filePath, {
33
+ start: { line: 0, character: 0 },
34
+ end: { line: 1_000_000, character: 0 },
35
+ }, diagnostics);
36
+ return { diagnostics, actions };
37
+ }
38
+ /** Find all references to a symbol */
39
+ async references(filePath, line, character) {
40
+ const client = await this.getClient(filePath);
41
+ return client.references(filePath, line, character);
42
+ }
43
+ /** Get a structured outline of all symbols in a file */
44
+ async outline(filePath) {
45
+ const client = await this.getClient(filePath);
46
+ return client.documentSymbols(filePath);
47
+ }
48
+ /** Rename a symbol across the project */
49
+ async rename(filePath, line, character, newName) {
50
+ const client = await this.getClient(filePath);
51
+ return client.rename(filePath, line, character, newName);
52
+ }
53
+ /** Get inferred type annotations for a line range */
54
+ async inlayHints(filePath, startLine, endLine) {
55
+ const client = await this.getClient(filePath);
56
+ return client.inlayHints(filePath, startLine, endLine);
57
+ }
58
+ /** Shut down all active LSP instances */
59
+ async shutdown() {
60
+ await Promise.all([...this.entries.values()].map(({ client, idleTimer }) => {
61
+ clearTimeout(idleTimer);
62
+ return client.shutdown();
63
+ }));
64
+ this.entries.clear();
65
+ }
66
+ async getClient(filePath) {
67
+ const projectRoot = findProjectRoot(filePath);
68
+ const existing = this.entries.get(projectRoot);
69
+ if (existing?.client.isAlive) {
70
+ this.resetIdleTimer(projectRoot, existing);
71
+ return existing.client;
72
+ }
73
+ if (existing) {
74
+ clearTimeout(existing.idleTimer);
75
+ this.entries.delete(projectRoot);
76
+ }
77
+ const rootUri = `file://${projectRoot}`;
78
+ const client = await LspClient.create(this.binaryPath, rootUri);
79
+ const entry = {
80
+ client,
81
+ idleTimer: this.startIdleTimer(projectRoot),
82
+ };
83
+ this.entries.set(projectRoot, entry);
84
+ return client;
85
+ }
86
+ startIdleTimer(projectRoot) {
87
+ return setTimeout(async () => {
88
+ const entry = this.entries.get(projectRoot);
89
+ if (entry) {
90
+ await entry.client.shutdown();
91
+ this.entries.delete(projectRoot);
92
+ }
93
+ }, this.idleTimeoutMs);
94
+ }
95
+ resetIdleTimer(projectRoot, entry) {
96
+ clearTimeout(entry.idleTimer);
97
+ entry.idleTimer = this.startIdleTimer(projectRoot);
98
+ }
99
+ }
100
+ /** Walk up from a file path to find the nearest tsconfig.json */
101
+ function findProjectRoot(filePath) {
102
+ let dir = dirname(filePath);
103
+ for (;;) {
104
+ if (existsSync(join(dir, "tsconfig.json")))
105
+ return dir;
106
+ const parent = dirname(dir);
107
+ if (parent === dir)
108
+ break;
109
+ dir = parent;
110
+ }
111
+ return dirname(filePath);
112
+ }
113
+ //# sourceMappingURL=pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pool.js","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { existsSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ const PLATFORM_PACKAGE = `@typescript/native-preview-${process.platform}-${process.arch}`;
5
+ /**
6
+ * Resolves the tsgo native binary path. Checks TSGO_PATH env var, then bun/npm
7
+ * global install locations. The native binary is required (not the Node
8
+ * wrapper) for stdio piping.
9
+ */
10
+ export function resolveTsgoBinary() {
11
+ const envPath = process.env.TSGO_PATH;
12
+ if (envPath) {
13
+ if (!existsSync(envPath))
14
+ throw new Error(`TSGO_PATH is set to "${envPath}" but the file does not exist`);
15
+ return envPath;
16
+ }
17
+ const exe = process.platform === "win32" ? "tsgo.exe" : "tsgo";
18
+ const candidates = [
19
+ join(homedir(), ".bun", "install", "global", "node_modules", PLATFORM_PACKAGE, "lib", exe),
20
+ join("/usr", "local", "lib", "node_modules", PLATFORM_PACKAGE, "lib", exe),
21
+ ];
22
+ for (const candidate of candidates) {
23
+ if (existsSync(candidate))
24
+ return candidate;
25
+ }
26
+ throw new Error([
27
+ "Could not find tsgo native binary.",
28
+ `Looked for package: ${PLATFORM_PACKAGE}`,
29
+ "Install globally: bun add -g @typescript/native-preview",
30
+ "Or set TSGO_PATH to the native binary path.",
31
+ ].join("\n"));
32
+ }
33
+ //# sourceMappingURL=resolve-binary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-binary.js","sourceRoot":"","sources":["../src/resolve-binary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,MAAM,gBAAgB,GAAG,8BAA8B,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE,CAAA;AAEzF;;;;GAIG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAA;IACrC,IAAI,OAAO,EAAE,CAAC;QACZ,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;YACtB,MAAM,IAAI,KAAK,CACb,wBAAwB,OAAO,+BAA+B,CAC/D,CAAA;QACH,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAA;IAC9D,MAAM,UAAU,GAAG;QACjB,IAAI,CACF,OAAO,EAAE,EACT,MAAM,EACN,SAAS,EACT,QAAQ,EACR,cAAc,EACd,gBAAgB,EAChB,KAAK,EACL,GAAG,CACJ;QACD,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,KAAK,EAAE,GAAG,CAAC;KAC3E,CAAA;IAED,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAA;IAC7C,CAAC;IAED,MAAM,IAAI,KAAK,CACb;QACE,oCAAoC;QACpC,uBAAuB,gBAAgB,EAAE;QACzC,yDAAyD;QACzD,6CAA6C;KAC9C,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAA;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@zachsents/ts-mcp",
3
+ "version": "0.3.0",
4
+ "description": "Give AI agents TypeScript type awareness",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "ts-mcp": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "keywords": [
14
+ "mcp",
15
+ "typescript",
16
+ "tsgo",
17
+ "type-inference",
18
+ "lsp",
19
+ "ai",
20
+ "agent"
21
+ ],
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/zachsents/ts-mcp.git"
25
+ },
26
+ "author": "Zach Sents",
27
+ "license": "MIT",
28
+ "scripts": {
29
+ "start": "bun run src/index.ts",
30
+ "build": "tsc -p tsconfig.build.json && shx chmod +x dist/index.js",
31
+ "lint": "oxlint --type-aware --fix --fix-suggestions",
32
+ "format": "prettier --write .",
33
+ "fix": "bun run lint && bun run format",
34
+ "typecheck": "tsc --noEmit",
35
+ "check": "bun run typecheck && bun run fix"
36
+ },
37
+ "devDependencies": {
38
+ "@types/bun": "latest",
39
+ "oxlint": "^1.51.0",
40
+ "oxlint-tsgolint": "^0.16.0",
41
+ "prettier": "^3.8.1",
42
+ "prettier-plugin-jsdoc": "^1.8.0",
43
+ "shx": "^0.4.0",
44
+ "typescript": "^5"
45
+ },
46
+ "dependencies": {
47
+ "@modelcontextprotocol/sdk": "^1.27.1",
48
+ "zod": "^4.3.6"
49
+ }
50
+ }