Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
0ed814d
feat(mcp): регистрация workspace инструментами вместо MCP roots
claude Aug 16, 2026
2181b5b
fix(mcp): выверить аннотации workspace-инструментов по спеке MCP
claude Aug 16, 2026
39547e2
docs(mcp): описать разметку инструментов аннотациями
claude Aug 16, 2026
1139d77
fix(mcp): регистрировать корень рабочей области, а не каталог исходников
claude Aug 16, 2026
9f3b200
refactor(mcp): выверить WorkspaceDto и снять гонки в workspace-инстру…
claude Aug 16, 2026
319ebec
refactor(mcp): убрать documents из WorkspaceDto, имя рабочей области …
claude Aug 16, 2026
700a206
docs(mcp): ревизия 2025-11-25 — протокола, а не SDK
claude Aug 16, 2026
135be09
refactor(mcp): читать имя рабочей области из реестра, а не дублироват…
claude Aug 16, 2026
4c8b93e
fix(mcp): убрать недостижимый фолбэк имени в WorkspaceDto
claude Aug 16, 2026
71d77ad
refactor(mcp): различать workspace и workspace folder по терминологии…
claude Aug 16, 2026
1fa0790
refactor(mcp): параметр root → workspaceFolder, поле root → uri
claude Aug 16, 2026
0943d18
refactor(mcp): владение рабочими папками и терминология workspace folder
claude Aug 16, 2026
cd53bfe
fix(mcp): не отдавать чужие рабочие папки и не терять их идентичность
claude Aug 17, 2026
0c6f21a
style(mcp): убрать замечания статического анализа по управлению папками
claude Aug 17, 2026
0d19709
style(mcp): вернуть простой перехват вместо объявления чужого IOExcep…
claude Aug 17, 2026
0c18988
fix(mcp): единая нормализация URI и честный отказ при удалении папки
claude Aug 17, 2026
871b48c
fix(mcp): не выпускать наружу внутреннее исключение реестра при сняти…
claude Aug 17, 2026
cb14e97
test(mcp): канонизировать временный каталог в тестах владения папками
claude Aug 17, 2026
958e88e
style(mcp): убрать импорт, оставшийся от перенесённых тестов нормализ…
claude Aug 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions docs/en/features/McpMode.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

BSL Language Server can act as a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server — exposing 1C (BSL) and OneScript code analysis to AI agents and tools that support MCP.

MCP tools run on top of the same engine as the LSP mode: the same parsing, the same providers. Workspaces are provided through [MCP roots](https://modelcontextprotocol.io/docs/concepts/roots) — the direct analog of LSP workspace folders.
MCP tools run on top of the same engine as the LSP mode: the same parsing, the same providers. Workspace folders are registered with the `register_workspace_folder`/`list_workspace_folders` tools — see the "Workspace folders" section below.

!!! warning "Experimental feature"
The MCP mode is built on Spring AI 2.0 (a milestone version at the time of writing). The API and behavior may change.
Expand Down Expand Up @@ -51,14 +51,35 @@ LSP over websocket and MCP over Streamable HTTP on the same web server:
java -jar bsl-language-server.jar websocket --mcp --server.port=8080
```

## Workspaces (MCP roots)
## Workspace folders

Source directories are provided by the client through MCP roots — just like an LSP client sends workspace folders. The server indexes the declared roots into the shared context and re-syncs them on change (`roots/list_changed`). In the combined modes (`lsp --mcp`, `websocket --mcp`) workspaces come from both the LSP client (workspace folders) and the MCP client (roots) into one shared context.
The terminology is LSP's: a **workspace folder** is a single project root directory, and the set of registered folders makes up the **workspace** this server serves. What gets registered and passed to the tools is a folder.

Every analysis tool answers only inside a registered workspace folder — a 1C configuration or OneScript project whose sources are indexed. A file outside every registered folder is not analysed, and the tools that are not bound to a file (`type_info`, `global_member_info`, `global_member_search`) require an explicit `workspaceFolder` argument.

The client workflow:

1. `list_workspace_folders` — see what is already registered and get the `uri` values.
2. `register_workspace_folder` with the project directory — if the project is not in the list yet. Pass the folder root: the directory an editor opens and an LSP client sends as a workspace folder, not a sources subfolder. It holds the sources (`src/cf` of a configuration, the OneScript sources) and, when present, the [configuration file](ConfigurationFile.md) `.bsl-language-server.json`, which is only read from the folder root. The tool indexes the sources and returns the folder's `uri`; registering an already registered directory does not re-index it.
3. `unregister_workspace_folder` — release the index when the project is no longer needed. Only folders registered over MCP can be removed: a folder that came from the LSP client is the editor's workspace folder and is left alone, because the client cannot get it back. A folder the client additionally declares as a root (see MCP roots below) stays indexed, which the result reports as `stillDeclaredByRoots`: the folder goes away once the last source releases it.

The error messages are self-contained: for an unknown or missing `workspaceFolder` the server lists the registered folders and names the tool that registers a new one, so an agent can recover without asking a human.

Additional sources of workspace folders:

- **LSP.** In the combined modes (`lsp --mcp`, `websocket --mcp`) workspace folders come from the LSP client into the same shared context — there is no need to register them over MCP, they show up in `list_workspace_folders` right away.
- **MCP roots.** Roots declared by the client through [MCP roots](https://modelcontextprotocol.io/docs/concepts/roots) are still indexed automatically, including re-sync on `notifications/roots/list_changed`. This works as long as the server speaks the `2025-11-25` revision of the protocol — the one implemented by the MCP SDK it is built on — where roots are still active.

!!! warning "MCP roots are deprecated"
In the [2026-07-28](https://modelcontextprotocol.io/specification/2026-07-28/changelog) revision of the specification the roots feature (together with sampling and logging) is marked deprecated, and the `notifications/roots/list_changed` notification is removed from the protocol. The suggested migration is to pass directories through tool parameters and server configuration — which is exactly what `register_workspace_folder`/`list_workspace_folders` do. Roots support is kept for compatibility with older clients; under the MCP feature lifecycle policy it cannot be removed earlier than twelve months after that revision, and this server will drop it when it moves to the new revision.

## Available tools

| Tool | Purpose |
| --- | --- |
| `list_workspace_folders` | Registered workspace folders: the `uri` for the other tools and the name |
Comment thread
coderabbitai[bot] marked this conversation as resolved.
| `register_workspace_folder` | Register a project directory as a workspace folder and index its sources; the name can be given explicitly, otherwise the directory name is used |
| `unregister_workspace_folder` | Remove a workspace folder and release its index |
| `analyze_file` | Diagnostics for a file |
| `document_symbols` | Symbol tree of a file (methods, regions, variables) |
| `find_references` | All references to the symbol at a position |
Expand All @@ -72,6 +93,8 @@ Source directories are provided by the client through MCP roots — just like an

Positions (`line`, `character`) are zero-based, as in LSP.

No tool modifies files on disk. The analysis tools are marked read-only (`readOnlyHint`), so a client should not ask for confirmation on every call. The workspace-folder management tools change server state and are therefore not read-only; `unregister_workspace_folder` is additionally marked destructive (`destructiveHint`) because it throws away the index that was built, so a client may reasonably ask for confirmation on that one.

## Launch options

| Option | Mode | Purpose |
Expand Down
29 changes: 26 additions & 3 deletions docs/features/McpMode.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

BSL Language Server умеет работать как сервер [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) — открывать возможности анализа кода 1С (BSL) и OneScript AI-агентам и инструментам, которые поддерживают MCP.

Инструменты MCP работают поверх того же движка, что и LSP-режим: тот же разбор, те же провайдеры. Рабочие пространства задаются через [MCP roots](https://modelcontextprotocol.io/docs/concepts/roots)прямой аналог workspace folders в LSP.
Инструменты MCP работают поверх того же движка, что и LSP-режим: тот же разбор, те же провайдеры. Рабочие папки регистрируются инструментами `register_workspace_folder`/`list_workspace_folders`см. раздел «Рабочие папки» ниже.

!!! warning "Экспериментальная возможность"
Режим MCP основан на Spring AI 2.0 (на момент написания — milestone-версия). API и поведение могут меняться.
Expand Down Expand Up @@ -51,14 +51,35 @@ LSP по websocket и MCP по Streamable HTTP на одном веб-серве
java -jar bsl-language-server.jar websocket --mcp --server.port=8080
```

## Рабочие пространства (MCP roots)
## Рабочие папки

Каталоги исходников задаёт клиент через MCP roots — так же, как LSP-клиент передаёт workspace folders. Сервер индексирует объявленные корни в общий контекст и пересинхронизирует их при изменении (`roots/list_changed`). В комбинированных режимах (`lsp --mcp`, `websocket --mcp`) рабочие пространства дают как LSP-клиент (workspace folders), так и MCP-клиент (roots) — в один общий контекст.
Терминология — из LSP: **рабочая папка** (workspace folder) — это один корневой каталог проекта, а множество зарегистрированных папок и составляет **рабочую область** (workspace), которую обслуживает сервер. Регистрируется и передаётся в инструменты именно папка.

Все инструменты анализа работают только внутри зарегистрированной рабочей папки — 1С-конфигурации или OneScript-проекта, исходники которого проиндексированы. Файл вне всех зарегистрированных папок не анализируется, а инструменты без привязки к файлу (`type_info`, `global_member_info`, `global_member_search`) требуют явного параметра `workspaceFolder`.

Порядок работы клиента:

1. `list_workspace_folders` — узнать, что уже зарегистрировано, и получить значения `uri`.
2. `register_workspace_folder` с каталогом проекта — если нужного проекта в списке нет. Передавать нужно корень рабочей папки: тот каталог, который открывают в IDE и который LSP-клиент присылает как workspace folder, а не подкаталог с исходниками. Внутри него лежат исходники (`src/cf` конфигурации, исходники OneScript) и, если он есть, [конфигурационный файл](ConfigurationFile.md) `.bsl-language-server.json` — он читается только из корня папки. Инструмент индексирует исходники и возвращает `uri` папки; повторная регистрация того же каталога переиндексацию не запускает.
3. `unregister_workspace_folder` — освободить индекс, когда проект больше не нужен. Инструмент удаляет только те папки, которые были зарегистрированы через MCP: папку, пришедшую от LSP-клиента, он не забирает — это рабочая папка редактора, и вернуть её клиент не сможет. Папку, которую сверх регистрации объявил корнем сам клиент (см. MCP roots ниже), сервер оставит проиндексированной и сообщит об этом признаком `stillDeclaredByRoots`: папка уходит, когда её отпустит последний источник.

Сообщения об ошибках самодостаточны: при неизвестном или отсутствующем `workspaceFolder` сервер перечисляет зарегистрированные папки и указывает, каким инструментом зарегистрировать недостающую, — агент может исправиться без участия человека.

Дополнительные источники рабочих папок:

- **LSP.** В комбинированных режимах (`lsp --mcp`, `websocket --mcp`) рабочие папки приходят от LSP-клиента (workspace folders) в тот же общий контекст — регистрировать их через MCP не нужно, они сразу видны в `list_workspace_folders`.
- **MCP roots.** Корни, объявленные клиентом через [MCP roots](https://modelcontextprotocol.io/docs/concepts/roots), по-прежнему индексируются автоматически, включая пересинхронизацию по `notifications/roots/list_changed`. Это работает, пока сервер говорит по ревизии протокола `2025-11-25` — той, что реализует используемый MCP SDK, — где roots ещё активны.

!!! warning "MCP roots объявлены устаревшими"
В ревизии спецификации [2026-07-28](https://modelcontextprotocol.io/specification/2026-07-28/changelog) механизм roots (вместе с sampling и logging) помечен как deprecated, а уведомление `notifications/roots/list_changed` из протокола удалено. В качестве замены спецификация предлагает передавать каталоги через параметры инструментов и конфигурацию сервера — это и делают `register_workspace_folder`/`list_workspace_folders`. Поддержка roots сохраняется как совместимость со старыми клиентами; по политике жизненного цикла возможностей MCP удалить их могут не раньше чем через 12 месяцев после этой ревизии, а в сервере они уйдут вместе с переходом на неё.

## Доступные инструменты

| Инструмент | Назначение |
| --- | --- |
| `list_workspace_folders` | Зарегистрированные рабочие папки: `uri` для остальных инструментов и имя |
| `register_workspace_folder` | Регистрация каталога проекта как рабочей папки с индексацией исходников; имя можно задать явно, иначе берётся имя каталога |
| `unregister_workspace_folder` | Удаление рабочей папки и освобождение её индекса |
| `analyze_file` | Диагностики по файлу |
| `document_symbols` | Дерево символов файла (методы, области, переменные) |
| `find_references` | Все ссылки на символ в позиции |
Expand All @@ -72,6 +93,8 @@ java -jar bsl-language-server.jar websocket --mcp --server.port=8080

Позиции (`line`, `character`) нумеруются с нуля, как в LSP.

Ни один инструмент не меняет файлы на диске. Инструменты анализа помечены как read-only (`readOnlyHint`) — клиент не должен спрашивать подтверждение на каждый вызов. Инструменты управления рабочими папками меняют состояние сервера, поэтому read-only не помечены; `unregister_workspace_folder` дополнительно помечен разрушающим (`destructiveHint`), так как выбрасывает собранный индекс, — на него клиент вправе запросить подтверждение.

## Параметры запуска

| Параметр | Режим | Назначение |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@
* (Server-Sent Events по HTTP) или {@code streamable} (Streamable HTTP). Сервер поднимает
* автоконфигурация Spring AI (профили {@code mcp,mcp-stdio} / {@code mcp,mcp-sse} /
* {@code mcp,mcp-streamable}); инструменты ({@code @McpTool}) работают через общий
* {@code ServerContextProvider}. Рабочие пространства приходят от клиента через MCP roots
* (см. {@code McpRootsChangeConsumer}) — аналог workspace folders в LSP.
* {@code ServerContextProvider}. Рабочие пространства клиент регистрирует инструментами
* {@code register_workspace_folder}/{@code list_workspace_folders}; дополнительно поддерживаются MCP roots
* (см. {@code McpRootsChangeConsumer}).
* <p>
* Для {@code stdio} команда применяет глобальную конфигурацию и блокируется до отключения клиента
* (EOF stdin). Для HTTP-транспортов ({@code sse}, {@code streamable}) процесс жив за счёт
Expand Down
Loading
Loading