syntax-map-mcp 0.1.2 → 0.1.3
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/CHANGELOG.md +10 -0
- package/README.md +183 -1
- package/dist/analysis/context.js +54 -2
- package/dist/analysis/index.js +27 -11
- package/dist/analysis/summary.js +22 -0
- package/dist/tools.js +18 -5
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.1.3 - 2026-05-04
|
|
6
|
+
|
|
7
|
+
- README에 `summarize_file`, 인덱스 검색 도구, `get_index_status`의 입력/응답 예시를 추가했습니다.
|
|
8
|
+
- Python 파일의 `summarize_file.exports`가 top-level `__all__`을 기준으로 반환되는 동작을 문서화했습니다.
|
|
9
|
+
- 배포 전 `typecheck`, 테스트, 빌드, 패키징 dry-run을 한 번에 실행하는 `release:check` 스크립트를 추가했습니다.
|
|
10
|
+
- Python 파일의 top-level `__all__` 문자열 이름을 `summarize_file.exports`로 반환하도록 했습니다.
|
|
11
|
+
- 인덱스 검색 도구에 `includePreview` 옵션을 추가해 `previewMarkdown`을 반환할 수 있게 했습니다.
|
|
12
|
+
- `build_context`가 `indexedSearch` 입력으로 인덱스 검색 결과 기반 markdown 컨텍스트를 만들 수 있게 했습니다.
|
|
13
|
+
- 패키지 버전을 `0.1.3`으로 올렸습니다.
|
|
14
|
+
|
|
5
15
|
## 0.1.2 - 2026-05-04
|
|
6
16
|
|
|
7
17
|
- `summarize_file`의 `exports` 추출을 AST 기반으로 변경해 문자열 내부 텍스트가 export로 잘못 반환되지 않도록 했습니다.
|
package/README.md
CHANGED
|
@@ -47,10 +47,192 @@ npx -y syntax-map-mcp --workspace-root /path/to/workspace
|
|
|
47
47
|
|
|
48
48
|
`index_workspace`는 `workspaceRoot` 아래의 `.syntax-map-mcp/index.sqlite`에 인덱스를 저장합니다. 인덱싱 대상은 `.js`, `.jsx`, `.ts`, `.tsx`, `.py` 파일이며, `.git`, `.syntax-map-mcp`, `dist`, `node_modules` 디렉터리는 제외합니다.
|
|
49
49
|
|
|
50
|
-
파일 변경 여부는 `mtimeMs`와 `size`로 판단합니다. 다시 `index_workspace`를 호출하면 변경된 파일만 재파싱하고, 삭제된 파일은 인덱스에서 제거합니다. `search_symbols`, `find_indexed_definition`, `find_indexed_references`는 `isStale`, `staleFiles`, `refreshed`를 반환해 검색 결과가 최신 인덱스 기반인지 알려줍니다. 세 도구에 `refreshIfStale: true`를 전달하면 stale 파일이 있을 때 먼저 인덱스를 갱신한 뒤 검색합니다. 인덱스 검색 도구는 인덱스에 저장된 위치를 조회한 뒤 현재 파일에서 해당 줄 snippet을 읽어 반환합니다. `contextBefore`, `contextAfter`를 0-10 사이 정수로 전달하면 snippet 주변 라인도 함께 반환합니다. 자동 watch 모드는 아직 포함하지 않았습니다.
|
|
50
|
+
파일 변경 여부는 `mtimeMs`와 `size`로 판단합니다. 다시 `index_workspace`를 호출하면 변경된 파일만 재파싱하고, 삭제된 파일은 인덱스에서 제거합니다. `search_symbols`, `find_indexed_definition`, `find_indexed_references`는 `isStale`, `staleFiles`, `refreshed`를 반환해 검색 결과가 최신 인덱스 기반인지 알려줍니다. 세 도구에 `refreshIfStale: true`를 전달하면 stale 파일이 있을 때 먼저 인덱스를 갱신한 뒤 검색합니다. 인덱스 검색 도구는 인덱스에 저장된 위치를 조회한 뒤 현재 파일에서 해당 줄 snippet을 읽어 반환합니다. `contextBefore`, `contextAfter`를 0-10 사이 정수로 전달하면 snippet 주변 라인도 함께 반환합니다. `includePreview: true`를 전달하면 `path:line` 헤더와 코드블록으로 구성된 `previewMarkdown`도 함께 반환합니다. 자동 watch 모드는 아직 포함하지 않았습니다.
|
|
51
51
|
|
|
52
52
|
`summarize_file`은 `sources` 필드로 `symbols`, `imports`, `exports`가 어떤 방식으로 추출되었는지 반환합니다.
|
|
53
53
|
|
|
54
|
+
Python은 JavaScript/TypeScript처럼 명시적인 `export` 문법이 없으므로, top-level `__all__`에 선언된 문자열 이름을 `exports`로 반환합니다. `__all__`이 없으면 `exports`는 빈 배열입니다.
|
|
55
|
+
|
|
56
|
+
## 도구 사용 예시
|
|
57
|
+
|
|
58
|
+
### summarize_file
|
|
59
|
+
|
|
60
|
+
입력:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"path": "src/index.ts"
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
응답 일부:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"ok": true,
|
|
73
|
+
"path": "src/index.ts",
|
|
74
|
+
"language": "typescript",
|
|
75
|
+
"imports": ["import { createServer } from './server.js';"],
|
|
76
|
+
"exports": ["export async function main() {"],
|
|
77
|
+
"sources": {
|
|
78
|
+
"symbols": "ast",
|
|
79
|
+
"imports": "ast",
|
|
80
|
+
"exports": "ast"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### search_symbols
|
|
86
|
+
|
|
87
|
+
입력:
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"query": "UserService",
|
|
92
|
+
"kinds": ["class"],
|
|
93
|
+
"refreshIfStale": true,
|
|
94
|
+
"contextBefore": 2,
|
|
95
|
+
"contextAfter": 2,
|
|
96
|
+
"includePreview": true
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
응답 일부:
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"ok": true,
|
|
105
|
+
"isStale": false,
|
|
106
|
+
"refreshed": true,
|
|
107
|
+
"symbols": [
|
|
108
|
+
{
|
|
109
|
+
"path": "src/users.ts",
|
|
110
|
+
"name": "UserService",
|
|
111
|
+
"kind": "class",
|
|
112
|
+
"snippet": "export class UserService {",
|
|
113
|
+
"context": {
|
|
114
|
+
"before": ["export type UserId = User['id'];", ""],
|
|
115
|
+
"after": [" constructor(private readonly users: User[]) {}", ""]
|
|
116
|
+
},
|
|
117
|
+
"previewMarkdown": "src/users.ts:8\n\n```typescript\nexport type UserId = User['id'];\n\nexport class UserService {\n constructor(private readonly users: User[]) {}\n\n```"
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### find_indexed_definition
|
|
124
|
+
|
|
125
|
+
입력:
|
|
126
|
+
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"name": "UserService",
|
|
130
|
+
"refreshIfStale": true,
|
|
131
|
+
"contextBefore": 1,
|
|
132
|
+
"contextAfter": 1
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
응답 일부:
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"ok": true,
|
|
141
|
+
"total": 1,
|
|
142
|
+
"definitions": [
|
|
143
|
+
{
|
|
144
|
+
"path": "src/users.ts",
|
|
145
|
+
"name": "UserService",
|
|
146
|
+
"kind": "class",
|
|
147
|
+
"snippet": "export class UserService {"
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### find_indexed_references
|
|
154
|
+
|
|
155
|
+
입력:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{
|
|
159
|
+
"name": "formatUser",
|
|
160
|
+
"limit": 20,
|
|
161
|
+
"refreshIfStale": true
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
응답 일부:
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"ok": true,
|
|
170
|
+
"references": [
|
|
171
|
+
{
|
|
172
|
+
"path": "src/users.ts",
|
|
173
|
+
"name": "formatUser",
|
|
174
|
+
"nodeType": "identifier",
|
|
175
|
+
"snippet": "formatUser(defaultUser);"
|
|
176
|
+
}
|
|
177
|
+
]
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### build_context
|
|
182
|
+
|
|
183
|
+
파일 경로 기반 입력:
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"paths": ["src/users.ts", "src/index.ts"],
|
|
188
|
+
"detail": "compact"
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
인덱스 검색 기반 입력:
|
|
193
|
+
|
|
194
|
+
```json
|
|
195
|
+
{
|
|
196
|
+
"detail": "compact",
|
|
197
|
+
"indexedSearch": {
|
|
198
|
+
"query": "UserService",
|
|
199
|
+
"kinds": ["class"],
|
|
200
|
+
"refreshIfStale": true,
|
|
201
|
+
"contextBefore": 1,
|
|
202
|
+
"contextAfter": 1
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
응답 일부:
|
|
208
|
+
|
|
209
|
+
```json
|
|
210
|
+
{
|
|
211
|
+
"ok": true,
|
|
212
|
+
"markdown": "# Code Context\n\n## Indexed Search Results\n\n### UserService\n\nsrc/users.ts:8\n\n```typescript\nexport class UserService {\n```"
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### get_index_status
|
|
217
|
+
|
|
218
|
+
입력:
|
|
219
|
+
|
|
220
|
+
```json
|
|
221
|
+
{}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
응답 일부:
|
|
225
|
+
|
|
226
|
+
```json
|
|
227
|
+
{
|
|
228
|
+
"ok": true,
|
|
229
|
+
"indexedFiles": 12,
|
|
230
|
+
"symbols": 84,
|
|
231
|
+
"references": 231,
|
|
232
|
+
"staleFiles": 0
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
54
236
|
## 변경 이력
|
|
55
237
|
|
|
56
238
|
버전별 변경 내용은 [CHANGELOG.md](./CHANGELOG.md)를 참고하세요.
|
package/dist/analysis/context.js
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
|
+
import { searchSymbols } from './index.js';
|
|
1
2
|
import { summarizeFile } from './summary.js';
|
|
2
3
|
export async function buildContext(workspace, input) {
|
|
4
|
+
if (input.indexedSearch) {
|
|
5
|
+
return buildIndexedSearchContext(workspace, {
|
|
6
|
+
detail: input.detail,
|
|
7
|
+
indexedSearch: input.indexedSearch
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
if (!input.paths) {
|
|
11
|
+
return failure('Either paths or indexedSearch must be provided');
|
|
12
|
+
}
|
|
3
13
|
const summaries = [];
|
|
4
14
|
for (const filePath of input.paths) {
|
|
5
15
|
const summary = await summarizeFile(workspace, filePath);
|
|
@@ -12,8 +22,50 @@ export async function buildContext(workspace, input) {
|
|
|
12
22
|
markdown: renderMarkdown(summaries, input.detail)
|
|
13
23
|
};
|
|
14
24
|
}
|
|
15
|
-
function
|
|
16
|
-
|
|
25
|
+
async function buildIndexedSearchContext(workspace, input) {
|
|
26
|
+
const search = await searchSymbols(workspace, {
|
|
27
|
+
...input.indexedSearch,
|
|
28
|
+
includePreview: true
|
|
29
|
+
});
|
|
30
|
+
if (!search.ok)
|
|
31
|
+
return search;
|
|
32
|
+
const paths = [...new Set(search.symbols.map(symbol => symbol.path))];
|
|
33
|
+
const summaries = [];
|
|
34
|
+
for (const filePath of paths) {
|
|
35
|
+
const summary = await summarizeFile(workspace, filePath);
|
|
36
|
+
if (!summary.ok)
|
|
37
|
+
return summary;
|
|
38
|
+
summaries.push(summary);
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
ok: true,
|
|
42
|
+
markdown: renderMarkdown(summaries, input.detail, renderIndexedSearchResults(search.symbols))
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function renderMarkdown(summaries, detail, intro) {
|
|
46
|
+
return ['# Code Context', intro, ...summaries.map(summary => renderFile(summary, detail))]
|
|
47
|
+
.filter(Boolean)
|
|
48
|
+
.join('\n\n');
|
|
49
|
+
}
|
|
50
|
+
function renderIndexedSearchResults(symbols) {
|
|
51
|
+
const lines = ['## Indexed Search Results'];
|
|
52
|
+
if (symbols.length === 0) {
|
|
53
|
+
lines.push('', '- None');
|
|
54
|
+
return lines.join('\n');
|
|
55
|
+
}
|
|
56
|
+
for (const symbol of symbols) {
|
|
57
|
+
lines.push('', `### ${symbol.name}`, '', symbol.previewMarkdown ?? symbol.path);
|
|
58
|
+
}
|
|
59
|
+
return lines.join('\n');
|
|
60
|
+
}
|
|
61
|
+
function failure(message) {
|
|
62
|
+
return {
|
|
63
|
+
ok: false,
|
|
64
|
+
error: {
|
|
65
|
+
code: 'INDEX_ERROR',
|
|
66
|
+
message
|
|
67
|
+
}
|
|
68
|
+
};
|
|
17
69
|
}
|
|
18
70
|
function renderFile(summary, detail) {
|
|
19
71
|
const lines = [
|
package/dist/analysis/index.js
CHANGED
|
@@ -253,23 +253,39 @@ function sqlLikePattern(query) {
|
|
|
253
253
|
function rowValue(row, key) {
|
|
254
254
|
return row[key];
|
|
255
255
|
}
|
|
256
|
-
function snippetDetails(text, row, options) {
|
|
256
|
+
function snippetDetails(path, language, text, row, options) {
|
|
257
257
|
if (text === undefined)
|
|
258
258
|
return { snippet: '' };
|
|
259
259
|
const lines = text.split(/\r?\n/);
|
|
260
260
|
const snippet = lines[row] ?? '';
|
|
261
261
|
const beforeCount = options.contextBefore ?? 0;
|
|
262
262
|
const afterCount = options.contextAfter ?? 0;
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
return {
|
|
267
|
-
snippet,
|
|
268
|
-
context: {
|
|
263
|
+
const context = beforeCount === 0 && afterCount === 0
|
|
264
|
+
? undefined
|
|
265
|
+
: {
|
|
269
266
|
before: lines.slice(Math.max(0, row - beforeCount), row),
|
|
270
267
|
after: lines.slice(row + 1, row + 1 + afterCount)
|
|
271
|
-
}
|
|
268
|
+
};
|
|
269
|
+
const details = {
|
|
270
|
+
snippet,
|
|
272
271
|
};
|
|
272
|
+
if (context)
|
|
273
|
+
details.context = context;
|
|
274
|
+
if (options.includePreview) {
|
|
275
|
+
details.previewMarkdown = previewMarkdown(path, language, row, snippet, context);
|
|
276
|
+
}
|
|
277
|
+
return details;
|
|
278
|
+
}
|
|
279
|
+
function previewMarkdown(filePath, language, row, snippet, context) {
|
|
280
|
+
return [
|
|
281
|
+
`${filePath}:${row + 1}`,
|
|
282
|
+
'',
|
|
283
|
+
`\`\`\`${language}`,
|
|
284
|
+
...(context?.before ?? []),
|
|
285
|
+
snippet,
|
|
286
|
+
...(context?.after ?? []),
|
|
287
|
+
'```'
|
|
288
|
+
].join('\n');
|
|
273
289
|
}
|
|
274
290
|
export async function indexWorkspace(workspace) {
|
|
275
291
|
const indexPath = indexPathForWorkspace(workspace);
|
|
@@ -442,7 +458,7 @@ export async function findIndexedDefinitions(workspace, input) {
|
|
|
442
458
|
column: Number(selectionEndColumn)
|
|
443
459
|
}
|
|
444
460
|
},
|
|
445
|
-
...snippetDetails(file.ok ? file.text : undefined, startRow, input)
|
|
461
|
+
...snippetDetails(filePath, rowValue(row, 'language'), file.ok ? file.text : undefined, startRow, input)
|
|
446
462
|
});
|
|
447
463
|
}
|
|
448
464
|
}
|
|
@@ -509,7 +525,7 @@ export async function findIndexedReferences(workspace, input) {
|
|
|
509
525
|
column: Number(rowValue(row, 'end_column'))
|
|
510
526
|
}
|
|
511
527
|
},
|
|
512
|
-
...snippetDetails(file.ok ? file.text : undefined, startRow, input)
|
|
528
|
+
...snippetDetails(filePath, rowValue(row, 'language'), file.ok ? file.text : undefined, startRow, input)
|
|
513
529
|
});
|
|
514
530
|
}
|
|
515
531
|
}
|
|
@@ -608,7 +624,7 @@ export async function searchSymbols(workspace, input) {
|
|
|
608
624
|
column: Number(selectionEndColumn)
|
|
609
625
|
}
|
|
610
626
|
},
|
|
611
|
-
...snippetDetails(file.ok ? file.text : undefined, startRow, input)
|
|
627
|
+
...snippetDetails(filePath, rowValue(row, 'language'), file.ok ? file.text : undefined, startRow, input)
|
|
612
628
|
});
|
|
613
629
|
}
|
|
614
630
|
}
|
package/dist/analysis/summary.js
CHANGED
|
@@ -43,6 +43,9 @@ function isImportNode(language, nodeType) {
|
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
function findExports(parsed) {
|
|
46
|
+
if (parsed.language === 'python') {
|
|
47
|
+
return findPythonAllExports(parsed);
|
|
48
|
+
}
|
|
46
49
|
return parsed.tree.rootNode.namedChildren
|
|
47
50
|
.filter(node => isExportNode(parsed.language, node.type))
|
|
48
51
|
.map(node => firstLine(node.text));
|
|
@@ -57,6 +60,25 @@ function isExportNode(language, nodeType) {
|
|
|
57
60
|
return false;
|
|
58
61
|
}
|
|
59
62
|
}
|
|
63
|
+
function findPythonAllExports(parsed) {
|
|
64
|
+
return parsed.tree.rootNode.namedChildren.flatMap(node => pythonAllExportNames(node));
|
|
65
|
+
}
|
|
66
|
+
function pythonAllExportNames(node) {
|
|
67
|
+
if (node.type !== 'expression_statement')
|
|
68
|
+
return [];
|
|
69
|
+
const assignment = node.namedChildren[0];
|
|
70
|
+
if (!assignment || assignment.type !== 'assignment')
|
|
71
|
+
return [];
|
|
72
|
+
const [target, value] = assignment.namedChildren;
|
|
73
|
+
if (!target || !value || target.type !== 'identifier' || target.text !== '__all__')
|
|
74
|
+
return [];
|
|
75
|
+
if (value.type !== 'list' && value.type !== 'tuple')
|
|
76
|
+
return [];
|
|
77
|
+
return value.namedChildren
|
|
78
|
+
.filter(child => child.type === 'string')
|
|
79
|
+
.map(child => child.namedChildren.find(part => part.type === 'string_content')?.text ?? '')
|
|
80
|
+
.filter(Boolean);
|
|
81
|
+
}
|
|
60
82
|
function firstLine(text) {
|
|
61
83
|
return text.split(/\r\n|\r|\n/, 1)[0].trim();
|
|
62
84
|
}
|
package/dist/tools.js
CHANGED
|
@@ -146,8 +146,18 @@ export function registerTools(server, workspace) {
|
|
|
146
146
|
title: 'Build context',
|
|
147
147
|
description: 'Build markdown context for supported source files.',
|
|
148
148
|
inputSchema: {
|
|
149
|
-
paths: z.array(z.string()),
|
|
150
|
-
detail: detailSchema
|
|
149
|
+
paths: z.array(z.string()).optional(),
|
|
150
|
+
detail: detailSchema,
|
|
151
|
+
indexedSearch: z
|
|
152
|
+
.object({
|
|
153
|
+
query: z.string(),
|
|
154
|
+
kinds: z.array(symbolKindSchema).optional(),
|
|
155
|
+
limit: z.number().int().positive().max(500).optional(),
|
|
156
|
+
refreshIfStale: z.boolean().optional(),
|
|
157
|
+
contextBefore: contextLineCountSchema.optional(),
|
|
158
|
+
contextAfter: contextLineCountSchema.optional()
|
|
159
|
+
})
|
|
160
|
+
.optional()
|
|
151
161
|
}
|
|
152
162
|
}, handlers.buildContext);
|
|
153
163
|
server.registerTool('index_workspace', {
|
|
@@ -164,7 +174,8 @@ export function registerTools(server, workspace) {
|
|
|
164
174
|
limit: z.number().int().positive().max(500).optional(),
|
|
165
175
|
refreshIfStale: z.boolean().optional(),
|
|
166
176
|
contextBefore: contextLineCountSchema.optional(),
|
|
167
|
-
contextAfter: contextLineCountSchema.optional()
|
|
177
|
+
contextAfter: contextLineCountSchema.optional(),
|
|
178
|
+
includePreview: z.boolean().optional()
|
|
168
179
|
}
|
|
169
180
|
}, handlers.searchSymbols);
|
|
170
181
|
server.registerTool('find_indexed_definition', {
|
|
@@ -176,7 +187,8 @@ export function registerTools(server, workspace) {
|
|
|
176
187
|
limit: z.number().int().positive().max(500).optional(),
|
|
177
188
|
refreshIfStale: z.boolean().optional(),
|
|
178
189
|
contextBefore: contextLineCountSchema.optional(),
|
|
179
|
-
contextAfter: contextLineCountSchema.optional()
|
|
190
|
+
contextAfter: contextLineCountSchema.optional(),
|
|
191
|
+
includePreview: z.boolean().optional()
|
|
180
192
|
}
|
|
181
193
|
}, handlers.findIndexedDefinition);
|
|
182
194
|
server.registerTool('find_indexed_references', {
|
|
@@ -187,7 +199,8 @@ export function registerTools(server, workspace) {
|
|
|
187
199
|
limit: z.number().int().positive().max(500).optional(),
|
|
188
200
|
refreshIfStale: z.boolean().optional(),
|
|
189
201
|
contextBefore: contextLineCountSchema.optional(),
|
|
190
|
-
contextAfter: contextLineCountSchema.optional()
|
|
202
|
+
contextAfter: contextLineCountSchema.optional(),
|
|
203
|
+
includePreview: z.boolean().optional()
|
|
191
204
|
}
|
|
192
205
|
}, handlers.findIndexedReferences);
|
|
193
206
|
server.registerTool('get_index_status', {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "syntax-map-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Tree-sitter based code analysis MCP server",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
"build": "tsc -p tsconfig.json",
|
|
30
30
|
"test": "vitest run",
|
|
31
31
|
"test:watch": "vitest",
|
|
32
|
-
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
32
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
33
|
+
"release:check": "npm run typecheck && npm test && npm run build && npm pack --dry-run"
|
|
33
34
|
},
|
|
34
35
|
"dependencies": {
|
|
35
36
|
"@modelcontextprotocol/sdk": "^1.29.0",
|