├── .dockerignore ├── .editorconfig ├── .gitignore ├── .vscode └── settings.json ├── Dockerfile ├── LICENSE.txt ├── README.md ├── dev ├── README.md ├── dev.config.json ├── mcp-cli │ ├── npx.json │ ├── simple.json │ ├── with-config.json │ └── with-docker.json ├── prod.config.json └── proxy.js ├── package.json ├── poc ├── .python-version ├── README.md ├── config.json ├── main.py ├── pyproject.toml └── uv.lock ├── src ├── 3rdparty │ └── metaModel.ts ├── app.ts ├── config.ts ├── index.ts ├── logger.ts ├── lsp-manager.ts ├── lsp-methods.ts ├── lsp.ts ├── mcp.ts ├── resources │ ├── generated.protocol.schema.json │ └── metaModel.json └── tool-manager.ts ├── tsconfig.json └── yarn.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | .dockerignore 2 | Dockerfile 3 | ./dev/* 4 | !./dev/prod.config.json 5 | ./.git 6 | ./.gitignore 7 | ./poc 8 | ./.vscode 9 | 10 | ###### FROM .gitignore 11 | ### Python 12 | # Byte-compiled / optimized / DLL files 13 | __pycache__/ 14 | *.py[cod] 15 | *$py.class 16 | 17 | # C extensions 18 | *.so 19 | 20 | # Distribution / packaging 21 | .Python 22 | build/ 23 | develop-eggs/ 24 | dist/ 25 | downloads/ 26 | eggs/ 27 | .eggs/ 28 | lib/ 29 | lib64/ 30 | parts/ 31 | sdist/ 32 | var/ 33 | wheels/ 34 | share/python-wheels/ 35 | *.egg-info/ 36 | .installed.cfg 37 | *.egg 38 | MANIFEST 39 | 40 | # PyInstaller 41 | # Usually these files are written by a python script from a template 42 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 43 | *.manifest 44 | *.spec 45 | 46 | # Installer logs 47 | pip-log.txt 48 | pip-delete-this-directory.txt 49 | 50 | # Unit test / coverage reports 51 | htmlcov/ 52 | .tox/ 53 | .nox/ 54 | .coverage 55 | .coverage.* 56 | .cache 57 | nosetests.xml 58 | coverage.xml 59 | *.cover 60 | *.py,cover 61 | .hypothesis/ 62 | .pytest_cache/ 63 | cover/ 64 | 65 | # Translations 66 | *.mo 67 | *.pot 68 | 69 | # Django stuff: 70 | *.log 71 | local_settings.py 72 | db.sqlite3 73 | db.sqlite3-journal 74 | 75 | # Flask stuff: 76 | instance/ 77 | .webassets-cache 78 | 79 | # Scrapy stuff: 80 | .scrapy 81 | 82 | # Sphinx documentation 83 | docs/_build/ 84 | 85 | # PyBuilder 86 | .pybuilder/ 87 | target/ 88 | 89 | # Jupyter Notebook 90 | .ipynb_checkpoints 91 | 92 | # IPython 93 | profile_default/ 94 | ipython_config.py 95 | 96 | # pyenv 97 | # For a library or package, you might want to ignore these files since the code is 98 | # intended to run in multiple environments; otherwise, check them in: 99 | # .python-version 100 | 101 | # pipenv 102 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 103 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 104 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 105 | # install all needed dependencies. 106 | #Pipfile.lock 107 | 108 | # UV 109 | # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. 110 | # This is especially recommended for binary packages to ensure reproducibility, and is more 111 | # commonly ignored for libraries. 112 | #uv.lock 113 | 114 | # poetry 115 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 116 | # This is especially recommended for binary packages to ensure reproducibility, and is more 117 | # commonly ignored for libraries. 118 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 119 | #poetry.lock 120 | 121 | # pdm 122 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 123 | #pdm.lock 124 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 125 | # in version control. 126 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control 127 | .pdm.toml 128 | .pdm-python 129 | .pdm-build/ 130 | 131 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 132 | __pypackages__/ 133 | 134 | # Celery stuff 135 | celerybeat-schedule 136 | celerybeat.pid 137 | 138 | # SageMath parsed files 139 | *.sage.py 140 | 141 | # Environments 142 | .env 143 | .venv 144 | env/ 145 | venv/ 146 | ENV/ 147 | env.bak/ 148 | venv.bak/ 149 | 150 | # Spyder project settings 151 | .spyderproject 152 | .spyproject 153 | 154 | # Rope project settings 155 | .ropeproject 156 | 157 | # mkdocs documentation 158 | /site 159 | 160 | # mypy 161 | .mypy_cache/ 162 | .dmypy.json 163 | dmypy.json 164 | 165 | # Pyre type checker 166 | .pyre/ 167 | 168 | # pytype static type analyzer 169 | .pytype/ 170 | 171 | # Cython debug symbols 172 | cython_debug/ 173 | 174 | # PyCharm 175 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 176 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 177 | # and can be added to the global gitignore or merged into this file. For a more nuclear 178 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 179 | #.idea/ 180 | 181 | # Ruff stuff: 182 | .ruff_cache/ 183 | 184 | # PyPI configuration file 185 | .pypirc 186 | 187 | 188 | ### Node 189 | # Logs 190 | logs 191 | *.log 192 | npm-debug.log* 193 | yarn-debug.log* 194 | yarn-error.log* 195 | lerna-debug.log* 196 | .pnpm-debug.log* 197 | 198 | # Diagnostic reports (https://nodejs.org/api/report.html) 199 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 200 | 201 | # Runtime data 202 | pids 203 | *.pid 204 | *.seed 205 | *.pid.lock 206 | 207 | # Directory for instrumented libs generated by jscoverage/JSCover 208 | lib-cov 209 | 210 | # Coverage directory used by tools like istanbul 211 | coverage 212 | *.lcov 213 | 214 | # nyc test coverage 215 | .nyc_output 216 | 217 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 218 | .grunt 219 | 220 | # Bower dependency directory (https://bower.io/) 221 | bower_components 222 | 223 | # node-waf configuration 224 | .lock-wscript 225 | 226 | # Compiled binary addons (https://nodejs.org/api/addons.html) 227 | build/Release 228 | 229 | # Dependency directories 230 | node_modules/ 231 | jspm_packages/ 232 | 233 | # Snowpack dependency directory (https://snowpack.dev/) 234 | web_modules/ 235 | 236 | # TypeScript cache 237 | *.tsbuildinfo 238 | 239 | # Optional npm cache directory 240 | .npm 241 | 242 | # Optional eslint cache 243 | .eslintcache 244 | 245 | # Optional stylelint cache 246 | .stylelintcache 247 | 248 | # Microbundle cache 249 | .rpt2_cache/ 250 | .rts2_cache_cjs/ 251 | .rts2_cache_es/ 252 | .rts2_cache_umd/ 253 | 254 | # Optional REPL history 255 | .node_repl_history 256 | 257 | # Output of 'npm pack' 258 | *.tgz 259 | 260 | # Yarn Integrity file 261 | .yarn-integrity 262 | 263 | # dotenv environment variable files 264 | .env 265 | .env.development.local 266 | .env.test.local 267 | .env.production.local 268 | .env.local 269 | 270 | # parcel-bundler cache (https://parceljs.org/) 271 | .cache 272 | .parcel-cache 273 | 274 | # Next.js build output 275 | .next 276 | out 277 | 278 | # Nuxt.js build / generate output 279 | .nuxt 280 | dist 281 | 282 | # Gatsby files 283 | .cache/ 284 | # Comment in the public line in if your project uses Gatsby and not Next.js 285 | # https://nextjs.org/blog/next-9-1#public-directory-support 286 | # public 287 | 288 | # vuepress build output 289 | .vuepress/dist 290 | 291 | # vuepress v2.x temp and cache directory 292 | .temp 293 | .cache 294 | 295 | # vitepress build output 296 | **/.vitepress/dist 297 | 298 | # vitepress cache directory 299 | **/.vitepress/cache 300 | 301 | # Docusaurus cache and generated files 302 | .docusaurus 303 | 304 | # Serverless directories 305 | .serverless/ 306 | 307 | # FuseBox cache 308 | .fusebox/ 309 | 310 | # DynamoDB Local files 311 | .dynamodb/ 312 | 313 | # TernJS port file 314 | .tern-port 315 | 316 | # Stores VSCode versions used for testing VSCode extensions 317 | .vscode-test 318 | 319 | # yarn v2 320 | .yarn/cache 321 | .yarn/unplugged 322 | .yarn/build-state.yml 323 | .yarn/install-state.gz 324 | .pnp.* 325 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Python 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | cover/ 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | local_settings.py 62 | db.sqlite3 63 | db.sqlite3-journal 64 | 65 | # Flask stuff: 66 | instance/ 67 | .webassets-cache 68 | 69 | # Scrapy stuff: 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | .pybuilder/ 77 | target/ 78 | 79 | # Jupyter Notebook 80 | .ipynb_checkpoints 81 | 82 | # IPython 83 | profile_default/ 84 | ipython_config.py 85 | 86 | # pyenv 87 | # For a library or package, you might want to ignore these files since the code is 88 | # intended to run in multiple environments; otherwise, check them in: 89 | # .python-version 90 | 91 | # pipenv 92 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 93 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 94 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 95 | # install all needed dependencies. 96 | #Pipfile.lock 97 | 98 | # UV 99 | # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. 100 | # This is especially recommended for binary packages to ensure reproducibility, and is more 101 | # commonly ignored for libraries. 102 | #uv.lock 103 | 104 | # poetry 105 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 106 | # This is especially recommended for binary packages to ensure reproducibility, and is more 107 | # commonly ignored for libraries. 108 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 109 | #poetry.lock 110 | 111 | # pdm 112 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 113 | #pdm.lock 114 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 115 | # in version control. 116 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control 117 | .pdm.toml 118 | .pdm-python 119 | .pdm-build/ 120 | 121 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 122 | __pypackages__/ 123 | 124 | # Celery stuff 125 | celerybeat-schedule 126 | celerybeat.pid 127 | 128 | # SageMath parsed files 129 | *.sage.py 130 | 131 | # Environments 132 | .env 133 | .venv 134 | env/ 135 | venv/ 136 | ENV/ 137 | env.bak/ 138 | venv.bak/ 139 | 140 | # Spyder project settings 141 | .spyderproject 142 | .spyproject 143 | 144 | # Rope project settings 145 | .ropeproject 146 | 147 | # mkdocs documentation 148 | /site 149 | 150 | # mypy 151 | .mypy_cache/ 152 | .dmypy.json 153 | dmypy.json 154 | 155 | # Pyre type checker 156 | .pyre/ 157 | 158 | # pytype static type analyzer 159 | .pytype/ 160 | 161 | # Cython debug symbols 162 | cython_debug/ 163 | 164 | # PyCharm 165 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 166 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 167 | # and can be added to the global gitignore or merged into this file. For a more nuclear 168 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 169 | #.idea/ 170 | 171 | # Ruff stuff: 172 | .ruff_cache/ 173 | 174 | # PyPI configuration file 175 | .pypirc 176 | 177 | 178 | ### Node 179 | # Logs 180 | logs 181 | *.log 182 | npm-debug.log* 183 | yarn-debug.log* 184 | yarn-error.log* 185 | lerna-debug.log* 186 | .pnpm-debug.log* 187 | 188 | # Diagnostic reports (https://nodejs.org/api/report.html) 189 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 190 | 191 | # Runtime data 192 | pids 193 | *.pid 194 | *.seed 195 | *.pid.lock 196 | 197 | # Directory for instrumented libs generated by jscoverage/JSCover 198 | lib-cov 199 | 200 | # Coverage directory used by tools like istanbul 201 | coverage 202 | *.lcov 203 | 204 | # nyc test coverage 205 | .nyc_output 206 | 207 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 208 | .grunt 209 | 210 | # Bower dependency directory (https://bower.io/) 211 | bower_components 212 | 213 | # node-waf configuration 214 | .lock-wscript 215 | 216 | # Compiled binary addons (https://nodejs.org/api/addons.html) 217 | build/Release 218 | 219 | # Dependency directories 220 | node_modules/ 221 | jspm_packages/ 222 | 223 | # Snowpack dependency directory (https://snowpack.dev/) 224 | web_modules/ 225 | 226 | # TypeScript cache 227 | *.tsbuildinfo 228 | 229 | # Optional npm cache directory 230 | .npm 231 | 232 | # Optional eslint cache 233 | .eslintcache 234 | 235 | # Optional stylelint cache 236 | .stylelintcache 237 | 238 | # Microbundle cache 239 | .rpt2_cache/ 240 | .rts2_cache_cjs/ 241 | .rts2_cache_es/ 242 | .rts2_cache_umd/ 243 | 244 | # Optional REPL history 245 | .node_repl_history 246 | 247 | # Output of 'npm pack' 248 | *.tgz 249 | 250 | # Yarn Integrity file 251 | .yarn-integrity 252 | 253 | # dotenv environment variable files 254 | .env 255 | .env.development.local 256 | .env.test.local 257 | .env.production.local 258 | .env.local 259 | 260 | # parcel-bundler cache (https://parceljs.org/) 261 | .cache 262 | .parcel-cache 263 | 264 | # Next.js build output 265 | .next 266 | out 267 | 268 | # Nuxt.js build / generate output 269 | .nuxt 270 | dist 271 | 272 | # Gatsby files 273 | .cache/ 274 | # Comment in the public line in if your project uses Gatsby and not Next.js 275 | # https://nextjs.org/blog/next-9-1#public-directory-support 276 | # public 277 | 278 | # vuepress build output 279 | .vuepress/dist 280 | 281 | # vuepress v2.x temp and cache directory 282 | .temp 283 | .cache 284 | 285 | # vitepress build output 286 | **/.vitepress/dist 287 | 288 | # vitepress cache directory 289 | **/.vitepress/cache 290 | 291 | # Docusaurus cache and generated files 292 | .docusaurus 293 | 294 | # Serverless directories 295 | .serverless/ 296 | 297 | # FuseBox cache 298 | .fusebox/ 299 | 300 | # DynamoDB Local files 301 | .dynamodb/ 302 | 303 | # TernJS port file 304 | .tern-port 305 | 306 | # Stores VSCode versions used for testing VSCode extensions 307 | .vscode-test 308 | 309 | # yarn v2 310 | .yarn/cache 311 | .yarn/unplugged 312 | .yarn/build-state.yml 313 | .yarn/install-state.gz 314 | .pnp.* 315 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "lsps", 4 | "modelcontextprotocol", 5 | "multilspy", 6 | "pylsp", 7 | "Taskfile", 8 | "venv" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Note: This Dockerfile is optimized for iterating, not for production. 2 | # For production we can do a lot more to optimize the image size 3 | FROM node:20 AS builder 4 | 5 | RUN mkdir /app 6 | RUN npm install -g typescript 7 | 8 | WORKDIR /app 9 | 10 | COPY package.json . 11 | COPY yarn.lock . 12 | RUN yarn install --frozen-lockfile --ignore-scripts 13 | 14 | COPY . . 15 | RUN yarn build 16 | RUN npm prune --omit=dev 17 | 18 | COPY dev/prod.config.json /app/dist/config.json 19 | 20 | FROM node:20-slim 21 | WORKDIR /app 22 | 23 | RUN apt update 24 | 25 | # LSPs 26 | RUN npm install -g typescript && npm install -g typescript-language-server 27 | RUN apt install -y python3-pylsp 28 | 29 | COPY --from=builder /app/dist /app 30 | COPY --from=builder /app/node_modules /app/node_modules 31 | 32 | # Cleanup 33 | RUN apt clean && rm -rf /var/lib/apt/lists/* 34 | 35 | ENTRYPOINT ["node", "index.js", "--config", "/app/config.json"] 36 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 4 | files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 5 | modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software 6 | is furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 9 | 10 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 11 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 12 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 13 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LSP MCP 2 | An Model Context Protocol (MCP) server that provides LLMs/AI Agents with the capabilities of a language server protocol (LSP) server. This gives the AI the ability to get language aware context from the codebase. 3 | 4 | - [LSP MCP](#lsp-mcp) 5 | - [Example](#example) 6 | - [Warning](#warning) 7 | - [Features](#features) 8 | - [Quick Start](#quick-start) 9 | - [Claude Desktop](#claude-desktop) 10 | - [Using Docker (Recommended)](#using-docker-recommended) 11 | - [Using npx](#using-npx) 12 | - [Cursor](#cursor) 13 | - [MCP CLI Client](#mcp-cli-client) 14 | - [The ABCs (Introduction)](#the-abcs-introduction) 15 | - [What is an MCP?](#what-is-an-mcp) 16 | - [What is an LSP?](#what-is-an-lsp) 17 | - [Development](#development) 18 | - [Dependencies](#dependencies) 19 | - [Decisions](#decisions) 20 | - [Roadmap](#roadmap) 21 | - [References](#references) 22 | 23 | ## Example 24 | 25 | **Input:** 26 | ``` 27 | Use lsp to give me insights into the following typescript code: 28 | 29 | let foo = "bar"; 30 | function x() { 31 | let foo = 123; 32 | console.log(foo); 33 | } 34 | x(); 35 | console.log(foo); 36 | ``` 37 | 38 | **Output:** 39 | ``` 40 | I'll use LSP (Language Server Protocol) to analyze your TypeScript code. Let me break down what's happening: 41 | Here's what the code does and the insights from LSP analysis: 42 | 43 | 1. Variable Shadowing: 44 | 45 | There are two variables named foo: 46 | 47 | A global foo (string type) initialized with the value "bar" 48 | A local foo (number type) inside the function x() initialized with the value 123 49 | 50 | 2. Execution Flow: 51 | 52 | First, the global foo is declared and assigned the value "bar" 53 | When function x() is called, the local foo variable is declared and assigned 123 54 | The console.log(foo) inside the function outputs 123 (the local variable) 55 | After the function finishes, console.log(foo) outputs "bar" (the global variable) 56 | 57 | 3. Scope Isolation: 58 | 59 | The LSP confirms that TypeScript correctly identifies the different types: 60 | 61 | The global foo is a string type 62 | The local foo inside the function is a number type 63 | 64 | Changes to the local foo don't affect the global foo 65 | 66 | This is a classic example of variable shadowing in JavaScript/TypeScript, where a local variable with the same name as a global variable takes precedence within its scope. 67 | ``` 68 | 69 | ## Warning 70 | This is in a POC state. 71 | 72 | ## Features 73 | * Multiple LSPs (Multiple programming language support) at the same time, see [sample config](./dev/dev.config.json) 74 | * Dynamically generates supported LSP method from LSP JSON Schema, see [json schema](./src/resources/generated.protocol.schema.json) 75 | 76 | ## Quick Start 77 | ### Claude Desktop 78 | 79 | #### Using Docker (Recommended) 80 | 81 | Modify `claude_desktop_config.json` (As described in the [MCP Docs](https://modelcontextprotocol.io/quickstart/user#2-add-the-filesystem-mcp-server)) with the following: 82 | ```json 83 | { 84 | "mcpServers": { 85 | "lsp": { 86 | "command": "docker", 87 | "args": ["run", "-i", "--rm", "docker.io/jonrad/lsp-mcp:0.3.1"] 88 | } 89 | } 90 | } 91 | ``` 92 | 93 | You'll likely want to share some files with the container by passing docker `-v /local_dir:/remote_dir`. Then you can ask Claude about the files in `/remote_dir/`. 94 | 95 | #### Using npx 96 | Note: Claude Desktop is finicky with npx it seems. Sometimes it says the mcp fails but the tools still work. I'll look into this... later 😊 97 | 98 | ```json 99 | { 100 | "mcpServers": { 101 | "lsp": { 102 | "command": "npx", 103 | "args": ["-y", "--silent", "git+https://github.com/jonrad/lsp-mcp", "--lsp", "npx -y --silent -p 'typescript@5.7.3' -p 'typescript-language-server@4.3.3' typescript-language-server --stdio"] 104 | } 105 | } 106 | } 107 | ``` 108 | 109 | This will provide Claude with the LSP capabilities of the typescript language server. You can modify the language server by switching the `--lsp` argument (and then restarting Claude). 110 | 111 | Multiple LSPs at the same time is not yet supported. 112 | 113 | ### [Cursor](https://www.cursor.com/) 114 | Follow the instructions [provided by Cursor](https://docs.cursor.com/context/model-context-protocol). For settings, choose `Type` = `command` and `Command` = `docker run ...` as mentioned above for claude (eg `docker run -i --rm -v : jonrad/lsp-mcp:`) 115 | 116 | ### [MCP CLI Client](https://github.com/adhikasp/mcp-client-cli) 117 | Follow the instructions for Claude but the config file is located in `~/.llm/config.json` 118 | 119 | 120 | ## The ABCs (Introduction) 121 | ### What is an MCP? 122 | * [MCP](https://modelcontextprotocol.io/) - Documentation 123 | * [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) - MCP Server Python Library 124 | ### What is an LSP? 125 | * [LSP](https://microsoft.github.io/language-server-protocol/) - Documentation 126 | * [multilspy](https://github.com/microsoft/multilspy) - LSP Python Client Library 127 | ## Development 128 | ```bash 129 | yarn 130 | yarn mcp-cli # Interactive MCP tool to help with development 131 | yarn dev --help # Get the CLI help 132 | ``` 133 | ### Dependencies 134 | ### Decisions 135 | * ~~Using python - I want to leverage a client library that makes the startup of this simple. A lot of LSPs are created in node, but the mature client libraries seem to be dependent on vscode. I like the look of [multilspy](https://github.com/microsoft/multilspy), so we'll start with python. It helps that I already created a python MCP, so at least I'll have a leg up there~~ 136 | * ~~[uv](https://docs.astral.sh/uv/) for package management and such - I've been seeing this used more frequently lately and this is an excuse to learn it. Switching package managers in the future is annoying but doable. I may have to revisit this decision once implementing CI/CD. Maybe I can use this instead of a dependency on [taskfile](https://taskfile.dev/) as well? TBD~~ 137 | * Async when possible - It's 2025 138 | * Switching to node after all. POC with python was more successful than I expected. But, multilspy doesn't support the entire LSP spec and vscode's library will be easier to work with as node is arguably the defacto standard language of LSP servers/clients. 139 | * Using the low-level MCP SDK. I think I'll need more control and it's frankly not that complicated as compared to the higher level FastMCP. 140 | * Using [zod](https://zod.dev/) for config validation. It's already a dependency for the MCP SDK, so no reason to overthink it. 141 | * I've set to always use an LSP even for unknown languages (eg LLM provides a textDocument/documentSymbol request for python but there is no python LSP registered). I'll probably revisit this decision. 142 | * Decided to make the LSPs start only when they are asked something. May make configurable later, but for now this prevents overuse of resources. 143 | 144 | ### Roadmap 145 | This is just a list of things I'd like to do eventually. There is no timeline or order for these. 146 | * Figure out how to sync capabilities between the LSP client (this) and the LSP server 147 | * Auto generated the LSP JSON Schema or find where it's published 148 | * Make json schema a cli argument so we don't have the update code to support new ones 149 | * Connect to an already running LSP server (via a multiplexing LSP server?) 150 | * Switch to (Taskfile)[https://taskfile.dev/] 151 | * Create a proper release process 152 | 153 | ## References 154 | * [Generated LSP JSON Schema](https://gist.github.com/bollwyvl/7a128978b8ae89ab02bbd5b84d07a4b7#file-generated-protocol-schema-json) 155 | -------------------------------------------------------------------------------- /dev/README.md: -------------------------------------------------------------------------------- 1 | Developer helper tools and configurations go here 2 | -------------------------------------------------------------------------------- /dev/dev.config.json: -------------------------------------------------------------------------------- 1 | /* Comments are allowed in this config file, yay */ 2 | { 3 | "lsps": [ 4 | { 5 | "id": "typescript", // unique id for logging purposes only 6 | "extensions": ["ts", "tsx", "js", "jsx"], // helps identify which files to use this lsp for 7 | "languages": ["typescript", "javascript"], // if the LLM sends one of these key words as the language, use this lsp 8 | "command": "npx", 9 | "args": ["-y", "typescript-language-server", "--stdio"] 10 | }, 11 | { 12 | "id": "python", 13 | "extensions": ["py"], 14 | "languages": ["python", "python2", "python3"], 15 | "command": "uvx", 16 | "args": ["--from", "python-lsp-server", "pylsp"] 17 | } 18 | ], 19 | // optional filter for which LSP methods to support, defaults to all methods 20 | "methods": ["textDocument/documentSymbol"] 21 | } 22 | -------------------------------------------------------------------------------- /dev/mcp-cli/npx.json: -------------------------------------------------------------------------------- 1 | { 2 | "mcpServers": { 3 | "lsp": { 4 | "command": "npx", 5 | "args": ["-y", "--silent", "git+https://github.com/jonrad/lsp-mcp", "--lsp", "npx -y --silent -p 'typescript@5.7.3' -p 'typescript-language-server@4.3.3' typescript-language-server --stdio"] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /dev/mcp-cli/simple.json: -------------------------------------------------------------------------------- 1 | { 2 | "mcpServers": { 3 | "lsp": { 4 | "command": "sh", 5 | "args": [ 6 | "-c", 7 | "yarn dev:simple --lsp 'npx -y typescript-language-server --stdio' | tee mcp.log" 8 | ] 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /dev/mcp-cli/with-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "mcpServers": { 3 | "lsp": { 4 | "command": "sh", 5 | "args": ["-c", "yarn dev:simple -v -c dev/dev.config.json 2>&1 | tee mcp.log"] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /dev/mcp-cli/with-docker.json: -------------------------------------------------------------------------------- 1 | { 2 | "mcpServers": { 3 | "lsp": { 4 | "command": "sh", 5 | "args": ["-c", "docker run -i --rm -v $(pwd):$(pwd) jonrad/lsp-mcp"] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /dev/prod.config.json: -------------------------------------------------------------------------------- 1 | /* Comments are allowed in this config file, yay */ 2 | { 3 | "lsps": [ 4 | { 5 | "id": "typescript", // unique id for logging purposes only 6 | "extensions": ["ts", "tsx", "js", "jsx"], // helps identify which files to use this lsp for 7 | "languages": ["typescript", "javascript"], // if the LLM sends one of these key words as the language, use this lsp 8 | "command": "typescript-language-server", 9 | "args": ["--stdio"] 10 | }, 11 | { 12 | "id": "python", 13 | "extensions": ["py"], 14 | "languages": ["python", "python2", "python3"], 15 | "command": "pylsp", 16 | "args": [] 17 | } 18 | ] 19 | // "methods": ["textDocument/documentSymbol"] 20 | } 21 | -------------------------------------------------------------------------------- /dev/proxy.js: -------------------------------------------------------------------------------- 1 | // Pulled from https://stackoverflow.com/questions/35353164/how-can-i-log-and-proxy-all-stdio-to-a-sub-process 2 | // Run: node shim.js 3 | 4 | const { spawn } = require("child_process"); 5 | const { createWriteStream } = require("fs"); 6 | 7 | // Start another process and pipe its output to the console and to a log file 8 | // Pass our standard input too 9 | function startProcess(commandAndArguments, log) { 10 | var child = spawn(commandAndArguments[0], commandAndArguments.slice(1)); 11 | child.stdout.pipe(process.stdout); 12 | child.stderr.pipe(process.stderr); 13 | process.stdin.pipe(child.stdin); 14 | const logStream = createWriteStream(log); 15 | logStream.write("Starting process: " + commandAndArguments.join(" ") + "\n"); 16 | child.stdout.on("data", (data) => { 17 | logStream.write("Output: " + data + "\n"); 18 | }); 19 | child.stderr.on("data", (data) => { 20 | logStream.write("Error: " + data + "\n"); 21 | }); 22 | process.stdin.on("data", (data) => { 23 | logStream.write("Input: " + data + "\n"); 24 | }); 25 | } 26 | 27 | function agentShim() { 28 | //get command line args 29 | const args = process.argv.slice(2); 30 | startProcess( 31 | ["/Users/jonrad/projects/lsp-mcp/.venv/bin/jedi-language-server", ...args], 32 | "/tmp/shim.log", 33 | ); 34 | } 35 | 36 | agentShim(); 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lsp-mcp", 3 | "version": "1.0.0", 4 | "main": "dist/index.js", 5 | "types": "dist/index.d.ts", 6 | "repository": "git@github.com:jonrad/lsp-mcp.git", 7 | "author": "Jon Radchenko ", 8 | "license": "MIT", 9 | "bin": { 10 | "lsp-mcp": "dist/index.js" 11 | }, 12 | "files": [ 13 | "dist", 14 | "resources" 15 | ], 16 | "devDependencies": { 17 | "@types/node": "^22.13.5", 18 | "@typescript-eslint/eslint-plugin": "^8.24.1", 19 | "@typescript-eslint/parser": "^8.24.1", 20 | "eslint": "^9.21.0", 21 | "eslint-config-prettier": "^10.0.1", 22 | "eslint-plugin-prettier": "^5.2.3", 23 | "prettier": "^3.5.2", 24 | "rimraf": "^6.0.1", 25 | "ts-node": "^10.9.2", 26 | "typescript": "^5.7.3", 27 | "typescript-language-server": "^4.3.3" 28 | }, 29 | "scripts": { 30 | "build": "tsc && rimraf dist/resources && cp -R src/resources dist/", 31 | "build:docker": "docker build . -t jonrad/lsp-mcp", 32 | "prepare": "yarn build", 33 | "start": "node dist/index.js", 34 | "dev": "ts-node src/index.ts", 35 | "dev:simple": "yarn dev --methods textDocument/documentSymbol", 36 | "lint": "eslint . --ext .ts", 37 | "format": "prettier --write .", 38 | "test": "jest", 39 | 40 | "mcp-cli:simple": "npx @wong2/mcp-cli --config dev/mcp-cli/simple.json", 41 | "mcp-cli:config": "npx @wong2/mcp-cli --config dev/mcp-cli/with-config.json", 42 | "mcp-cli:npx": "npx @wong2/mcp-cli --config dev/mcp-cli/npx.json", 43 | "mcp-cli:docker": "npx @wong2/mcp-cli --config dev/mcp-cli/with-docker.json", 44 | 45 | 46 | "llm": "uvx --python 3.12 --from git+https://github.com/adhikasp/mcp-client-cli.git llm --text-only" 47 | }, 48 | "dependencies": { 49 | "@apidevtools/json-schema-ref-parser": "^11.9.1", 50 | "@modelcontextprotocol/sdk": "^1.5.0", 51 | "commander": "^13.1.0", 52 | "strip-json-comments": "^5.0.1", 53 | "vscode-languageserver-protocol": "^3.17.5", 54 | "zod": "^3.24.2" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /poc/.python-version: -------------------------------------------------------------------------------- 1 | 3.12 2 | -------------------------------------------------------------------------------- /poc/README.md: -------------------------------------------------------------------------------- 1 | # POC 2 | This directory holds an initial poc that has proven to work. It is no longer maintained and only used as a reference 3 | 4 | -------------------------------------------------------------------------------- /poc/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "mcpServers": { 3 | "lsp": { 4 | "command": "uv", 5 | "args": ["run", "main.py"] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /poc/main.py: -------------------------------------------------------------------------------- 1 | from typing import Callable 2 | from multilspy import LanguageServer 3 | from multilspy.multilspy_config import MultilspyConfig 4 | from multilspy.multilspy_logger import MultilspyLogger 5 | from mcp.server.fastmcp import FastMCP 6 | from mcp.types import ( 7 | Tool as MCPTool, 8 | ) 9 | import inspect 10 | import os 11 | import asyncio 12 | import logging 13 | 14 | logger = logging.getLogger(__name__) 15 | cwd = os.getcwd() 16 | 17 | def get_relative_path(file_path: str) -> str: 18 | return os.path.join(cwd, file_path) 19 | 20 | def build_mcp(lsp: LanguageServer) -> FastMCP: 21 | mcp = FastMCP("lsp") 22 | fns = [ 23 | lsp.request_document_symbols, 24 | lsp.request_definition, 25 | lsp.request_references, 26 | lsp.request_completions, 27 | lsp.request_hover, 28 | ] 29 | 30 | for fn in fns: 31 | add_tool(mcp, fn) 32 | return mcp 33 | 34 | def add_tool(mcp: FastMCP, fn: Callable) -> MCPTool: 35 | mcp.add_tool(fn=fn, name="lsp_" + fn.__name__, description=inspect.getdoc(fn)) 36 | 37 | async def main(): 38 | lsp = LanguageServer.create( 39 | MultilspyConfig.from_dict({"code_language": "python"}), 40 | MultilspyLogger(), 41 | cwd, 42 | ) 43 | 44 | mcp = build_mcp(lsp) 45 | 46 | logger.info("LSP starting...") 47 | async with lsp.start_server(): 48 | logger.info("LSP started") 49 | 50 | await mcp.run_stdio_async() 51 | 52 | 53 | if __name__ == "__main__": 54 | try: 55 | asyncio.run(main()) 56 | except Exception as e: 57 | logger.error(f"Error: {e}") 58 | raise e 59 | -------------------------------------------------------------------------------- /poc/pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "lsp-mcp" 3 | version = "0.1.0" 4 | description = "Add your description here" 5 | readme = "README.md" 6 | requires-python = ">=3.12" 7 | dependencies = [ 8 | "mcp==1.3.0", 9 | "multilspy==0.0.12", 10 | ] 11 | 12 | [tool.uv] 13 | override-dependencies = [ 14 | "pydantic>=2.0,<3.0" 15 | ] -------------------------------------------------------------------------------- /poc/uv.lock: -------------------------------------------------------------------------------- 1 | version = 1 2 | revision = 1 3 | requires-python = ">=3.12" 4 | 5 | [manifest] 6 | overrides = [{ name = "pydantic", specifier = ">=2.0,<3.0" }] 7 | 8 | [[package]] 9 | name = "annotated-types" 10 | version = "0.7.0" 11 | source = { registry = "https://pypi.org/simple" } 12 | sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 } 13 | wheels = [ 14 | { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, 15 | ] 16 | 17 | [[package]] 18 | name = "anyio" 19 | version = "4.8.0" 20 | source = { registry = "https://pypi.org/simple" } 21 | dependencies = [ 22 | { name = "idna" }, 23 | { name = "sniffio" }, 24 | { name = "typing-extensions", marker = "python_full_version < '3.13'" }, 25 | ] 26 | sdist = { url = "https://files.pythonhosted.org/packages/a3/73/199a98fc2dae33535d6b8e8e6ec01f8c1d76c9adb096c6b7d64823038cde/anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a", size = 181126 } 27 | wheels = [ 28 | { url = "https://files.pythonhosted.org/packages/46/eb/e7f063ad1fec6b3178a3cd82d1a3c4de82cccf283fc42746168188e1cdd5/anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a", size = 96041 }, 29 | ] 30 | 31 | [[package]] 32 | name = "attrs" 33 | version = "25.1.0" 34 | source = { registry = "https://pypi.org/simple" } 35 | sdist = { url = "https://files.pythonhosted.org/packages/49/7c/fdf464bcc51d23881d110abd74b512a42b3d5d376a55a831b44c603ae17f/attrs-25.1.0.tar.gz", hash = "sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e", size = 810562 } 36 | wheels = [ 37 | { url = "https://files.pythonhosted.org/packages/fc/30/d4986a882011f9df997a55e6becd864812ccfcd821d64aac8570ee39f719/attrs-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a", size = 63152 }, 38 | ] 39 | 40 | [[package]] 41 | name = "cattrs" 42 | version = "24.1.2" 43 | source = { registry = "https://pypi.org/simple" } 44 | dependencies = [ 45 | { name = "attrs" }, 46 | ] 47 | sdist = { url = "https://files.pythonhosted.org/packages/64/65/af6d57da2cb32c076319b7489ae0958f746949d407109e3ccf4d115f147c/cattrs-24.1.2.tar.gz", hash = "sha256:8028cfe1ff5382df59dd36474a86e02d817b06eaf8af84555441bac915d2ef85", size = 426462 } 48 | wheels = [ 49 | { url = "https://files.pythonhosted.org/packages/c8/d5/867e75361fc45f6de75fe277dd085627a9db5ebb511a87f27dc1396b5351/cattrs-24.1.2-py3-none-any.whl", hash = "sha256:67c7495b760168d931a10233f979b28dc04daf853b30752246f4f8471c6d68d0", size = 66446 }, 50 | ] 51 | 52 | [[package]] 53 | name = "certifi" 54 | version = "2025.1.31" 55 | source = { registry = "https://pypi.org/simple" } 56 | sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 } 57 | wheels = [ 58 | { url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 }, 59 | ] 60 | 61 | [[package]] 62 | name = "charset-normalizer" 63 | version = "3.4.1" 64 | source = { registry = "https://pypi.org/simple" } 65 | sdist = { url = "https://files.pythonhosted.org/packages/16/b0/572805e227f01586461c80e0fd25d65a2115599cc9dad142fee4b747c357/charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3", size = 123188 } 66 | wheels = [ 67 | { url = "https://files.pythonhosted.org/packages/0a/9a/dd1e1cdceb841925b7798369a09279bd1cf183cef0f9ddf15a3a6502ee45/charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545", size = 196105 }, 68 | { url = "https://files.pythonhosted.org/packages/d3/8c/90bfabf8c4809ecb648f39794cf2a84ff2e7d2a6cf159fe68d9a26160467/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7", size = 140404 }, 69 | { url = "https://files.pythonhosted.org/packages/ad/8f/e410d57c721945ea3b4f1a04b74f70ce8fa800d393d72899f0a40526401f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757", size = 150423 }, 70 | { url = "https://files.pythonhosted.org/packages/f0/b8/e6825e25deb691ff98cf5c9072ee0605dc2acfca98af70c2d1b1bc75190d/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa", size = 143184 }, 71 | { url = "https://files.pythonhosted.org/packages/3e/a2/513f6cbe752421f16d969e32f3583762bfd583848b763913ddab8d9bfd4f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d", size = 145268 }, 72 | { url = "https://files.pythonhosted.org/packages/74/94/8a5277664f27c3c438546f3eb53b33f5b19568eb7424736bdc440a88a31f/charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616", size = 147601 }, 73 | { url = "https://files.pythonhosted.org/packages/7c/5f/6d352c51ee763623a98e31194823518e09bfa48be2a7e8383cf691bbb3d0/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b", size = 141098 }, 74 | { url = "https://files.pythonhosted.org/packages/78/d4/f5704cb629ba5ab16d1d3d741396aec6dc3ca2b67757c45b0599bb010478/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d", size = 149520 }, 75 | { url = "https://files.pythonhosted.org/packages/c5/96/64120b1d02b81785f222b976c0fb79a35875457fa9bb40827678e54d1bc8/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a", size = 152852 }, 76 | { url = "https://files.pythonhosted.org/packages/84/c9/98e3732278a99f47d487fd3468bc60b882920cef29d1fa6ca460a1fdf4e6/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9", size = 150488 }, 77 | { url = "https://files.pythonhosted.org/packages/13/0e/9c8d4cb99c98c1007cc11eda969ebfe837bbbd0acdb4736d228ccaabcd22/charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1", size = 146192 }, 78 | { url = "https://files.pythonhosted.org/packages/b2/21/2b6b5b860781a0b49427309cb8670785aa543fb2178de875b87b9cc97746/charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35", size = 95550 }, 79 | { url = "https://files.pythonhosted.org/packages/21/5b/1b390b03b1d16c7e382b561c5329f83cc06623916aab983e8ab9239c7d5c/charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f", size = 102785 }, 80 | { url = "https://files.pythonhosted.org/packages/38/94/ce8e6f63d18049672c76d07d119304e1e2d7c6098f0841b51c666e9f44a0/charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda", size = 195698 }, 81 | { url = "https://files.pythonhosted.org/packages/24/2e/dfdd9770664aae179a96561cc6952ff08f9a8cd09a908f259a9dfa063568/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313", size = 140162 }, 82 | { url = "https://files.pythonhosted.org/packages/24/4e/f646b9093cff8fc86f2d60af2de4dc17c759de9d554f130b140ea4738ca6/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9", size = 150263 }, 83 | { url = "https://files.pythonhosted.org/packages/5e/67/2937f8d548c3ef6e2f9aab0f6e21001056f692d43282b165e7c56023e6dd/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b", size = 142966 }, 84 | { url = "https://files.pythonhosted.org/packages/52/ed/b7f4f07de100bdb95c1756d3a4d17b90c1a3c53715c1a476f8738058e0fa/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11", size = 144992 }, 85 | { url = "https://files.pythonhosted.org/packages/96/2c/d49710a6dbcd3776265f4c923bb73ebe83933dfbaa841c5da850fe0fd20b/charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f", size = 147162 }, 86 | { url = "https://files.pythonhosted.org/packages/b4/41/35ff1f9a6bd380303dea55e44c4933b4cc3c4850988927d4082ada230273/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd", size = 140972 }, 87 | { url = "https://files.pythonhosted.org/packages/fb/43/c6a0b685fe6910d08ba971f62cd9c3e862a85770395ba5d9cad4fede33ab/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2", size = 149095 }, 88 | { url = "https://files.pythonhosted.org/packages/4c/ff/a9a504662452e2d2878512115638966e75633519ec11f25fca3d2049a94a/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886", size = 152668 }, 89 | { url = "https://files.pythonhosted.org/packages/6c/71/189996b6d9a4b932564701628af5cee6716733e9165af1d5e1b285c530ed/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601", size = 150073 }, 90 | { url = "https://files.pythonhosted.org/packages/e4/93/946a86ce20790e11312c87c75ba68d5f6ad2208cfb52b2d6a2c32840d922/charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd", size = 145732 }, 91 | { url = "https://files.pythonhosted.org/packages/cd/e5/131d2fb1b0dddafc37be4f3a2fa79aa4c037368be9423061dccadfd90091/charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407", size = 95391 }, 92 | { url = "https://files.pythonhosted.org/packages/27/f2/4f9a69cc7712b9b5ad8fdb87039fd89abba997ad5cbe690d1835d40405b0/charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971", size = 102702 }, 93 | { url = "https://files.pythonhosted.org/packages/0e/f6/65ecc6878a89bb1c23a086ea335ad4bf21a588990c3f535a227b9eea9108/charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85", size = 49767 }, 94 | ] 95 | 96 | [[package]] 97 | name = "click" 98 | version = "8.1.8" 99 | source = { registry = "https://pypi.org/simple" } 100 | dependencies = [ 101 | { name = "colorama", marker = "sys_platform == 'win32'" }, 102 | ] 103 | sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } 104 | wheels = [ 105 | { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 }, 106 | ] 107 | 108 | [[package]] 109 | name = "colorama" 110 | version = "0.4.6" 111 | source = { registry = "https://pypi.org/simple" } 112 | sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } 113 | wheels = [ 114 | { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, 115 | ] 116 | 117 | [[package]] 118 | name = "docstring-to-markdown" 119 | version = "0.15" 120 | source = { registry = "https://pypi.org/simple" } 121 | sdist = { url = "https://files.pythonhosted.org/packages/7a/ad/6a66abd14676619bd56f6b924c96321a2e2d7d86558841d94a30023eec53/docstring-to-markdown-0.15.tar.gz", hash = "sha256:e146114d9c50c181b1d25505054a8d0f7a476837f0da2c19f07e06eaed52b73d", size = 29246 } 122 | wheels = [ 123 | { url = "https://files.pythonhosted.org/packages/c1/cf/4eee59f6c4111b3e80cc32cf6bac483a90646f5c8693e84496c9855e8e38/docstring_to_markdown-0.15-py3-none-any.whl", hash = "sha256:27afb3faedba81e34c33521c32bbd258d7fbb79eedf7d29bc4e81080e854aec0", size = 21640 }, 124 | ] 125 | 126 | [[package]] 127 | name = "h11" 128 | version = "0.14.0" 129 | source = { registry = "https://pypi.org/simple" } 130 | sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 } 131 | wheels = [ 132 | { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 }, 133 | ] 134 | 135 | [[package]] 136 | name = "httpcore" 137 | version = "1.0.7" 138 | source = { registry = "https://pypi.org/simple" } 139 | dependencies = [ 140 | { name = "certifi" }, 141 | { name = "h11" }, 142 | ] 143 | sdist = { url = "https://files.pythonhosted.org/packages/6a/41/d7d0a89eb493922c37d343b607bc1b5da7f5be7e383740b4753ad8943e90/httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c", size = 85196 } 144 | wheels = [ 145 | { url = "https://files.pythonhosted.org/packages/87/f5/72347bc88306acb359581ac4d52f23c0ef445b57157adedb9aee0cd689d2/httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd", size = 78551 }, 146 | ] 147 | 148 | [[package]] 149 | name = "httpx" 150 | version = "0.28.1" 151 | source = { registry = "https://pypi.org/simple" } 152 | dependencies = [ 153 | { name = "anyio" }, 154 | { name = "certifi" }, 155 | { name = "httpcore" }, 156 | { name = "idna" }, 157 | ] 158 | sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 } 159 | wheels = [ 160 | { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 }, 161 | ] 162 | 163 | [[package]] 164 | name = "httpx-sse" 165 | version = "0.4.0" 166 | source = { registry = "https://pypi.org/simple" } 167 | sdist = { url = "https://files.pythonhosted.org/packages/4c/60/8f4281fa9bbf3c8034fd54c0e7412e66edbab6bc74c4996bd616f8d0406e/httpx-sse-0.4.0.tar.gz", hash = "sha256:1e81a3a3070ce322add1d3529ed42eb5f70817f45ed6ec915ab753f961139721", size = 12624 } 168 | wheels = [ 169 | { url = "https://files.pythonhosted.org/packages/e1/9b/a181f281f65d776426002f330c31849b86b31fc9d848db62e16f03ff739f/httpx_sse-0.4.0-py3-none-any.whl", hash = "sha256:f329af6eae57eaa2bdfd962b42524764af68075ea87370a2de920af5341e318f", size = 7819 }, 170 | ] 171 | 172 | [[package]] 173 | name = "idna" 174 | version = "3.10" 175 | source = { registry = "https://pypi.org/simple" } 176 | sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } 177 | wheels = [ 178 | { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, 179 | ] 180 | 181 | [[package]] 182 | name = "jedi" 183 | version = "0.19.2" 184 | source = { registry = "https://pypi.org/simple" } 185 | dependencies = [ 186 | { name = "parso" }, 187 | ] 188 | sdist = { url = "https://files.pythonhosted.org/packages/72/3a/79a912fbd4d8dd6fbb02bf69afd3bb72cf0c729bb3063c6f4498603db17a/jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", size = 1231287 } 189 | wheels = [ 190 | { url = "https://files.pythonhosted.org/packages/c0/5a/9cac0c82afec3d09ccd97c8b6502d48f165f9124db81b4bcb90b4af974ee/jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9", size = 1572278 }, 191 | ] 192 | 193 | [[package]] 194 | name = "jedi-language-server" 195 | version = "0.41.1" 196 | source = { registry = "https://pypi.org/simple" } 197 | dependencies = [ 198 | { name = "cattrs" }, 199 | { name = "docstring-to-markdown" }, 200 | { name = "jedi" }, 201 | { name = "lsprotocol" }, 202 | { name = "pygls" }, 203 | ] 204 | sdist = { url = "https://files.pythonhosted.org/packages/b0/4b/01c621c534c66792e67d9554b75483e0614672f9e3f469d665854725f807/jedi_language_server-0.41.1.tar.gz", hash = "sha256:3f15ca5cc28e728564f7d63583e171b418025582447ce023512e3f2b2d71ebae", size = 28947 } 205 | wheels = [ 206 | { url = "https://files.pythonhosted.org/packages/36/06/2d5336c20edd75dd65a39cb8fdc7fca2baf7e3a0ecf3992e30ca4b591d0d/jedi_language_server-0.41.1-py3-none-any.whl", hash = "sha256:ca9b3e7f48b70f0988d85ffde4f01dd1ab94c8e0f69e8c6424e6657117b44f91", size = 27816 }, 207 | ] 208 | 209 | [[package]] 210 | name = "lsp-mcp" 211 | version = "0.1.0" 212 | source = { virtual = "." } 213 | dependencies = [ 214 | { name = "mcp" }, 215 | { name = "multilspy" }, 216 | ] 217 | 218 | [package.metadata] 219 | requires-dist = [ 220 | { name = "mcp", specifier = "==1.3.0" }, 221 | { name = "multilspy", specifier = "==0.0.12" }, 222 | ] 223 | 224 | [[package]] 225 | name = "lsprotocol" 226 | version = "2023.0.1" 227 | source = { registry = "https://pypi.org/simple" } 228 | dependencies = [ 229 | { name = "attrs" }, 230 | { name = "cattrs" }, 231 | ] 232 | sdist = { url = "https://files.pythonhosted.org/packages/9d/f6/6e80484ec078d0b50699ceb1833597b792a6c695f90c645fbaf54b947e6f/lsprotocol-2023.0.1.tar.gz", hash = "sha256:cc5c15130d2403c18b734304339e51242d3018a05c4f7d0f198ad6e0cd21861d", size = 69434 } 233 | wheels = [ 234 | { url = "https://files.pythonhosted.org/packages/8d/37/2351e48cb3309673492d3a8c59d407b75fb6630e560eb27ecd4da03adc9a/lsprotocol-2023.0.1-py3-none-any.whl", hash = "sha256:c75223c9e4af2f24272b14c6375787438279369236cd568f596d4951052a60f2", size = 70826 }, 235 | ] 236 | 237 | [[package]] 238 | name = "mcp" 239 | version = "1.3.0" 240 | source = { registry = "https://pypi.org/simple" } 241 | dependencies = [ 242 | { name = "anyio" }, 243 | { name = "httpx" }, 244 | { name = "httpx-sse" }, 245 | { name = "pydantic" }, 246 | { name = "pydantic-settings" }, 247 | { name = "sse-starlette" }, 248 | { name = "starlette" }, 249 | { name = "uvicorn" }, 250 | ] 251 | sdist = { url = "https://files.pythonhosted.org/packages/6b/b6/81e5f2490290351fc97bf46c24ff935128cb7d34d68e3987b522f26f7ada/mcp-1.3.0.tar.gz", hash = "sha256:f409ae4482ce9d53e7ac03f3f7808bcab735bdfc0fba937453782efb43882d45", size = 150235 } 252 | wheels = [ 253 | { url = "https://files.pythonhosted.org/packages/d0/d2/a9e87b506b2094f5aa9becc1af5178842701b27217fa43877353da2577e3/mcp-1.3.0-py3-none-any.whl", hash = "sha256:2829d67ce339a249f803f22eba5e90385eafcac45c94b00cab6cef7e8f217211", size = 70672 }, 254 | ] 255 | 256 | [[package]] 257 | name = "multilspy" 258 | version = "0.0.12" 259 | source = { registry = "https://pypi.org/simple" } 260 | dependencies = [ 261 | { name = "jedi-language-server" }, 262 | { name = "pydantic" }, 263 | { name = "requests" }, 264 | ] 265 | sdist = { url = "https://files.pythonhosted.org/packages/68/a8/5453d9425fbef529b2a66dd68ce8c4b584b5622bf972dfdd251d6f30983f/multilspy-0.0.12.tar.gz", hash = "sha256:d6166302d15cda6d1c6820e9d0aac0a30382cb76dfc5fa2d1cee9f873289eb9c", size = 112339 } 266 | wheels = [ 267 | { url = "https://files.pythonhosted.org/packages/c0/c3/aeddbd7fda437520614978e80df342070060f3f5a1dfc49d7e2f8010a624/multilspy-0.0.12-py3-none-any.whl", hash = "sha256:e06f7ef7c388793eaaa2d4a6bb91dd9ef3efc78090b34ca1d2343b52062c57fc", size = 125230 }, 268 | ] 269 | 270 | [[package]] 271 | name = "parso" 272 | version = "0.8.4" 273 | source = { registry = "https://pypi.org/simple" } 274 | sdist = { url = "https://files.pythonhosted.org/packages/66/94/68e2e17afaa9169cf6412ab0f28623903be73d1b32e208d9e8e541bb086d/parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d", size = 400609 } 275 | wheels = [ 276 | { url = "https://files.pythonhosted.org/packages/c6/ac/dac4a63f978e4dcb3c6d3a78c4d8e0192a113d288502a1216950c41b1027/parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", size = 103650 }, 277 | ] 278 | 279 | [[package]] 280 | name = "pydantic" 281 | version = "2.10.6" 282 | source = { registry = "https://pypi.org/simple" } 283 | dependencies = [ 284 | { name = "annotated-types" }, 285 | { name = "pydantic-core" }, 286 | { name = "typing-extensions" }, 287 | ] 288 | sdist = { url = "https://files.pythonhosted.org/packages/b7/ae/d5220c5c52b158b1de7ca89fc5edb72f304a70a4c540c84c8844bf4008de/pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236", size = 761681 } 289 | wheels = [ 290 | { url = "https://files.pythonhosted.org/packages/f4/3c/8cc1cc84deffa6e25d2d0c688ebb80635dfdbf1dbea3e30c541c8cf4d860/pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", size = 431696 }, 291 | ] 292 | 293 | [[package]] 294 | name = "pydantic-core" 295 | version = "2.27.2" 296 | source = { registry = "https://pypi.org/simple" } 297 | dependencies = [ 298 | { name = "typing-extensions" }, 299 | ] 300 | sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443 } 301 | wheels = [ 302 | { url = "https://files.pythonhosted.org/packages/d6/74/51c8a5482ca447871c93e142d9d4a92ead74de6c8dc5e66733e22c9bba89/pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", size = 1893127 }, 303 | { url = "https://files.pythonhosted.org/packages/d3/f3/c97e80721735868313c58b89d2de85fa80fe8dfeeed84dc51598b92a135e/pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", size = 1811340 }, 304 | { url = "https://files.pythonhosted.org/packages/9e/91/840ec1375e686dbae1bd80a9e46c26a1e0083e1186abc610efa3d9a36180/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", size = 1822900 }, 305 | { url = "https://files.pythonhosted.org/packages/f6/31/4240bc96025035500c18adc149aa6ffdf1a0062a4b525c932065ceb4d868/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934", size = 1869177 }, 306 | { url = "https://files.pythonhosted.org/packages/fa/20/02fbaadb7808be578317015c462655c317a77a7c8f0ef274bc016a784c54/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6", size = 2038046 }, 307 | { url = "https://files.pythonhosted.org/packages/06/86/7f306b904e6c9eccf0668248b3f272090e49c275bc488a7b88b0823444a4/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c", size = 2685386 }, 308 | { url = "https://files.pythonhosted.org/packages/8d/f0/49129b27c43396581a635d8710dae54a791b17dfc50c70164866bbf865e3/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2", size = 1997060 }, 309 | { url = "https://files.pythonhosted.org/packages/0d/0f/943b4af7cd416c477fd40b187036c4f89b416a33d3cc0ab7b82708a667aa/pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4", size = 2004870 }, 310 | { url = "https://files.pythonhosted.org/packages/35/40/aea70b5b1a63911c53a4c8117c0a828d6790483f858041f47bab0b779f44/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3", size = 1999822 }, 311 | { url = "https://files.pythonhosted.org/packages/f2/b3/807b94fd337d58effc5498fd1a7a4d9d59af4133e83e32ae39a96fddec9d/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4", size = 2130364 }, 312 | { url = "https://files.pythonhosted.org/packages/fc/df/791c827cd4ee6efd59248dca9369fb35e80a9484462c33c6649a8d02b565/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57", size = 2158303 }, 313 | { url = "https://files.pythonhosted.org/packages/9b/67/4e197c300976af185b7cef4c02203e175fb127e414125916bf1128b639a9/pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc", size = 1834064 }, 314 | { url = "https://files.pythonhosted.org/packages/1f/ea/cd7209a889163b8dcca139fe32b9687dd05249161a3edda62860430457a5/pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9", size = 1989046 }, 315 | { url = "https://files.pythonhosted.org/packages/bc/49/c54baab2f4658c26ac633d798dab66b4c3a9bbf47cff5284e9c182f4137a/pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b", size = 1885092 }, 316 | { url = "https://files.pythonhosted.org/packages/41/b1/9bc383f48f8002f99104e3acff6cba1231b29ef76cfa45d1506a5cad1f84/pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b", size = 1892709 }, 317 | { url = "https://files.pythonhosted.org/packages/10/6c/e62b8657b834f3eb2961b49ec8e301eb99946245e70bf42c8817350cbefc/pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154", size = 1811273 }, 318 | { url = "https://files.pythonhosted.org/packages/ba/15/52cfe49c8c986e081b863b102d6b859d9defc63446b642ccbbb3742bf371/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9", size = 1823027 }, 319 | { url = "https://files.pythonhosted.org/packages/b1/1c/b6f402cfc18ec0024120602bdbcebc7bdd5b856528c013bd4d13865ca473/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9", size = 1868888 }, 320 | { url = "https://files.pythonhosted.org/packages/bd/7b/8cb75b66ac37bc2975a3b7de99f3c6f355fcc4d89820b61dffa8f1e81677/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1", size = 2037738 }, 321 | { url = "https://files.pythonhosted.org/packages/c8/f1/786d8fe78970a06f61df22cba58e365ce304bf9b9f46cc71c8c424e0c334/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a", size = 2685138 }, 322 | { url = "https://files.pythonhosted.org/packages/a6/74/d12b2cd841d8724dc8ffb13fc5cef86566a53ed358103150209ecd5d1999/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e", size = 1997025 }, 323 | { url = "https://files.pythonhosted.org/packages/a0/6e/940bcd631bc4d9a06c9539b51f070b66e8f370ed0933f392db6ff350d873/pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4", size = 2004633 }, 324 | { url = "https://files.pythonhosted.org/packages/50/cc/a46b34f1708d82498c227d5d80ce615b2dd502ddcfd8376fc14a36655af1/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27", size = 1999404 }, 325 | { url = "https://files.pythonhosted.org/packages/ca/2d/c365cfa930ed23bc58c41463bae347d1005537dc8db79e998af8ba28d35e/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee", size = 2130130 }, 326 | { url = "https://files.pythonhosted.org/packages/f4/d7/eb64d015c350b7cdb371145b54d96c919d4db516817f31cd1c650cae3b21/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1", size = 2157946 }, 327 | { url = "https://files.pythonhosted.org/packages/a4/99/bddde3ddde76c03b65dfd5a66ab436c4e58ffc42927d4ff1198ffbf96f5f/pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", size = 1834387 }, 328 | { url = "https://files.pythonhosted.org/packages/71/47/82b5e846e01b26ac6f1893d3c5f9f3a2eb6ba79be26eef0b759b4fe72946/pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", size = 1990453 }, 329 | { url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186 }, 330 | ] 331 | 332 | [[package]] 333 | name = "pydantic-settings" 334 | version = "2.8.0" 335 | source = { registry = "https://pypi.org/simple" } 336 | dependencies = [ 337 | { name = "pydantic" }, 338 | { name = "python-dotenv" }, 339 | ] 340 | sdist = { url = "https://files.pythonhosted.org/packages/ca/a2/ad2511ede77bb424f3939e5148a56d968cdc6b1462620d24b2a1f4ab65b4/pydantic_settings-2.8.0.tar.gz", hash = "sha256:88e2ca28f6e68ea102c99c3c401d6c9078e68a5df600e97b43891c34e089500a", size = 83347 } 341 | wheels = [ 342 | { url = "https://files.pythonhosted.org/packages/c1/a9/3b9642025174bbe67e900785fb99c9bfe91ea584b0b7126ff99945c24a0e/pydantic_settings-2.8.0-py3-none-any.whl", hash = "sha256:c782c7dc3fb40e97b238e713c25d26f64314aece2e91abcff592fcac15f71820", size = 30746 }, 343 | ] 344 | 345 | [[package]] 346 | name = "pygls" 347 | version = "1.3.1" 348 | source = { registry = "https://pypi.org/simple" } 349 | dependencies = [ 350 | { name = "cattrs" }, 351 | { name = "lsprotocol" }, 352 | ] 353 | sdist = { url = "https://files.pythonhosted.org/packages/86/b9/41d173dad9eaa9db9c785a85671fc3d68961f08d67706dc2e79011e10b5c/pygls-1.3.1.tar.gz", hash = "sha256:140edceefa0da0e9b3c533547c892a42a7d2fd9217ae848c330c53d266a55018", size = 45527 } 354 | wheels = [ 355 | { url = "https://files.pythonhosted.org/packages/11/19/b74a10dd24548e96e8c80226cbacb28b021bc3a168a7d2709fb0d0185348/pygls-1.3.1-py3-none-any.whl", hash = "sha256:6e00f11efc56321bdeb6eac04f6d86131f654c7d49124344a9ebb968da3dd91e", size = 56031 }, 356 | ] 357 | 358 | [[package]] 359 | name = "python-dotenv" 360 | version = "1.0.1" 361 | source = { registry = "https://pypi.org/simple" } 362 | sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115 } 363 | wheels = [ 364 | { url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863 }, 365 | ] 366 | 367 | [[package]] 368 | name = "requests" 369 | version = "2.32.3" 370 | source = { registry = "https://pypi.org/simple" } 371 | dependencies = [ 372 | { name = "certifi" }, 373 | { name = "charset-normalizer" }, 374 | { name = "idna" }, 375 | { name = "urllib3" }, 376 | ] 377 | sdist = { url = "https://files.pythonhosted.org/packages/63/70/2bf7780ad2d390a8d301ad0b550f1581eadbd9a20f896afe06353c2a2913/requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760", size = 131218 } 378 | wheels = [ 379 | { url = "https://files.pythonhosted.org/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6", size = 64928 }, 380 | ] 381 | 382 | [[package]] 383 | name = "sniffio" 384 | version = "1.3.1" 385 | source = { registry = "https://pypi.org/simple" } 386 | sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } 387 | wheels = [ 388 | { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, 389 | ] 390 | 391 | [[package]] 392 | name = "sse-starlette" 393 | version = "2.2.1" 394 | source = { registry = "https://pypi.org/simple" } 395 | dependencies = [ 396 | { name = "anyio" }, 397 | { name = "starlette" }, 398 | ] 399 | sdist = { url = "https://files.pythonhosted.org/packages/71/a4/80d2a11af59fe75b48230846989e93979c892d3a20016b42bb44edb9e398/sse_starlette-2.2.1.tar.gz", hash = "sha256:54470d5f19274aeed6b2d473430b08b4b379ea851d953b11d7f1c4a2c118b419", size = 17376 } 400 | wheels = [ 401 | { url = "https://files.pythonhosted.org/packages/d9/e0/5b8bd393f27f4a62461c5cf2479c75a2cc2ffa330976f9f00f5f6e4f50eb/sse_starlette-2.2.1-py3-none-any.whl", hash = "sha256:6410a3d3ba0c89e7675d4c273a301d64649c03a5ef1ca101f10b47f895fd0e99", size = 10120 }, 402 | ] 403 | 404 | [[package]] 405 | name = "starlette" 406 | version = "0.46.0" 407 | source = { registry = "https://pypi.org/simple" } 408 | dependencies = [ 409 | { name = "anyio" }, 410 | ] 411 | sdist = { url = "https://files.pythonhosted.org/packages/44/b6/fb9a32e3c5d59b1e383c357534c63c2d3caa6f25bf3c59dd89d296ecbaec/starlette-0.46.0.tar.gz", hash = "sha256:b359e4567456b28d473d0193f34c0de0ed49710d75ef183a74a5ce0499324f50", size = 2575568 } 412 | wheels = [ 413 | { url = "https://files.pythonhosted.org/packages/41/94/8af675a62e3c91c2dee47cf92e602cfac86e8767b1a1ac3caf1b327c2ab0/starlette-0.46.0-py3-none-any.whl", hash = "sha256:913f0798bd90ba90a9156383bcf1350a17d6259451d0d8ee27fc0cf2db609038", size = 71991 }, 414 | ] 415 | 416 | [[package]] 417 | name = "typing-extensions" 418 | version = "4.12.2" 419 | source = { registry = "https://pypi.org/simple" } 420 | sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } 421 | wheels = [ 422 | { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, 423 | ] 424 | 425 | [[package]] 426 | name = "urllib3" 427 | version = "2.3.0" 428 | source = { registry = "https://pypi.org/simple" } 429 | sdist = { url = "https://files.pythonhosted.org/packages/aa/63/e53da845320b757bf29ef6a9062f5c669fe997973f966045cb019c3f4b66/urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d", size = 307268 } 430 | wheels = [ 431 | { url = "https://files.pythonhosted.org/packages/c8/19/4ec628951a74043532ca2cf5d97b7b14863931476d117c471e8e2b1eb39f/urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df", size = 128369 }, 432 | ] 433 | 434 | [[package]] 435 | name = "uvicorn" 436 | version = "0.34.0" 437 | source = { registry = "https://pypi.org/simple" } 438 | dependencies = [ 439 | { name = "click" }, 440 | { name = "h11" }, 441 | ] 442 | sdist = { url = "https://files.pythonhosted.org/packages/4b/4d/938bd85e5bf2edeec766267a5015ad969730bb91e31b44021dfe8b22df6c/uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9", size = 76568 } 443 | wheels = [ 444 | { url = "https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4", size = 62315 }, 445 | ] 446 | -------------------------------------------------------------------------------- /src/3rdparty/metaModel.ts: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | * ------------------------------------------------------------------------------------------ */ 5 | 6 | export type BaseTypes = 'URI' | 'DocumentUri' | 'integer' | 'uinteger' | 'decimal' | 'RegExp' | 'string' | 'boolean' | 'null'; 7 | 8 | export type TypeKind = 'base' | 'reference' | 'array' | 'map' | 'and' | 'or' | 'tuple' | 'literal' | 'stringLiteral' | 'integerLiteral' | 'booleanLiteral'; 9 | 10 | /** 11 | * Indicates in which direction a message is sent in the protocol. 12 | */ 13 | export type MessageDirection = 'clientToServer' | 'serverToClient' | 'both'; 14 | 15 | /** 16 | * Represents a base type like `string` or `DocumentUri`. 17 | */ 18 | export type BaseType = { 19 | kind: 'base'; 20 | name: BaseTypes; 21 | }; 22 | 23 | /** 24 | * Represents a reference to another type (e.g. `TextDocument`). 25 | * This is either a `Structure`, a `Enumeration` or a `TypeAlias` 26 | * in the same meta model. 27 | */ 28 | export type ReferenceType = { 29 | kind: 'reference'; 30 | name: string; 31 | }; 32 | 33 | /** 34 | * Represents an array type (e.g. `TextDocument[]`). 35 | */ 36 | export type ArrayType = { 37 | kind: 'array'; 38 | element: Type; 39 | }; 40 | 41 | /** 42 | * Represents a type that can be used as a key in a 43 | * map type. If a reference type is used then the 44 | * type must either resolve to a `string` or `integer` 45 | * type. (e.g. `type ChangeAnnotationIdentifier === string`). 46 | */ 47 | export type MapKeyType = { kind: 'base'; name: 'URI' | 'DocumentUri' | 'string' | 'integer' } | ReferenceType; 48 | 49 | /** 50 | * Represents a JSON object map 51 | * (e.g. `interface Map { [key: K] => V; }`). 52 | */ 53 | export type MapType = { 54 | kind: 'map'; 55 | key: MapKeyType; 56 | value: Type; 57 | }; 58 | 59 | /** 60 | * Represents an `and`type 61 | * (e.g. TextDocumentParams & WorkDoneProgressParams`). 62 | */ 63 | export type AndType = { 64 | kind: 'and'; 65 | items: Type[]; 66 | }; 67 | 68 | /** 69 | * Represents an `or` type 70 | * (e.g. `Location | LocationLink`). 71 | */ 72 | export type OrType = { 73 | kind: 'or'; 74 | items: Type[]; 75 | }; 76 | 77 | /** 78 | * Represents a `tuple` type 79 | * (e.g. `[integer, integer]`). 80 | */ 81 | export type TupleType = { 82 | kind: 'tuple'; 83 | items: Type[]; 84 | }; 85 | 86 | /** 87 | * Represents a literal structure 88 | * (e.g. `property: { start: uinteger; end: uinteger; }`). 89 | */ 90 | export type StructureLiteralType = { 91 | kind: 'literal'; 92 | value: StructureLiteral; 93 | }; 94 | 95 | /** 96 | * Represents a string literal type 97 | * (e.g. `kind: 'rename'`). 98 | */ 99 | export type StringLiteralType = { 100 | kind: 'stringLiteral'; 101 | value: string; 102 | }; 103 | 104 | export type IntegerLiteralType = { 105 | /** 106 | * Represents an integer literal type 107 | * (e.g. `kind: 1`). 108 | */ 109 | kind: 'integerLiteral'; 110 | value: number; 111 | }; 112 | 113 | /** 114 | * Represents a boolean literal type 115 | * (e.g. `kind: true`). 116 | */ 117 | export type BooleanLiteralType = { 118 | kind: 'booleanLiteral'; 119 | value: boolean; 120 | }; 121 | 122 | export type Type = BaseType | ReferenceType | ArrayType | MapType | AndType | OrType | TupleType | StructureLiteralType | StringLiteralType | IntegerLiteralType | BooleanLiteralType; 123 | 124 | /** 125 | * Represents a LSP request 126 | */ 127 | export type Request = { 128 | /** 129 | * The request's method name. 130 | */ 131 | method: string; 132 | 133 | /** 134 | * The type name of the request if any. 135 | */ 136 | typeName?: string; 137 | 138 | /** 139 | * The parameter type(s) if any. 140 | */ 141 | params?: Type | Type[]; 142 | 143 | /** 144 | * The result type. 145 | */ 146 | result: Type; 147 | 148 | /** 149 | * Optional partial result type if the request 150 | * supports partial result reporting. 151 | */ 152 | partialResult?: Type; 153 | 154 | /** 155 | * An optional error data type. 156 | */ 157 | errorData?: Type; 158 | 159 | /** 160 | * Optional a dynamic registration method if it 161 | * different from the request's method. 162 | */ 163 | registrationMethod?: string; 164 | 165 | /** 166 | * Optional registration options if the request 167 | * supports dynamic registration. 168 | */ 169 | registrationOptions?: Type; 170 | 171 | /** 172 | * The direction in which this request is sent 173 | * in the protocol. 174 | */ 175 | messageDirection: MessageDirection; 176 | 177 | /** 178 | * An optional documentation; 179 | */ 180 | documentation?: string; 181 | 182 | /** 183 | * Since when (release number) this request is 184 | * available. Is undefined if not known. 185 | */ 186 | since?: string; 187 | 188 | /** 189 | * All since tags in case there was more than one tag. 190 | * Is undefined if not known. 191 | */ 192 | sinceTags?: string[]; 193 | 194 | /** 195 | * Whether this is a proposed feature. If omitted 196 | * the feature is final. 197 | */ 198 | proposed?: boolean; 199 | 200 | /** 201 | * Whether the request is deprecated or not. If deprecated 202 | * the property contains the deprecation message. 203 | */ 204 | deprecated?: string; 205 | 206 | /** 207 | * The client capability property path if any. 208 | */ 209 | clientCapability?: string; 210 | 211 | /** 212 | * The server capability property path if any. 213 | */ 214 | serverCapability?: string; 215 | }; 216 | 217 | /** 218 | * Represents a LSP notification 219 | */ 220 | export type Notification = { 221 | /** 222 | * The notifications's method name. 223 | */ 224 | method: string; 225 | 226 | /** 227 | * The type name of the notifications if any. 228 | */ 229 | typeName?: string; 230 | 231 | /** 232 | * The parameter type(s) if any. 233 | */ 234 | params?: Type | Type[]; 235 | 236 | /** 237 | * Optional a dynamic registration method if it 238 | * different from the notifications's method. 239 | */ 240 | registrationMethod?: string; 241 | 242 | /** 243 | * Optional registration options if the notification 244 | * supports dynamic registration. 245 | */ 246 | registrationOptions?: Type; 247 | 248 | /** 249 | * The direction in which this notification is sent 250 | * in the protocol. 251 | */ 252 | messageDirection: MessageDirection; 253 | 254 | /** 255 | * An optional documentation; 256 | */ 257 | documentation?: string; 258 | 259 | /** 260 | * Since when (release number) this notification is 261 | * available. Is undefined if not known. 262 | */ 263 | since?: string; 264 | 265 | /** 266 | * All since tags in case there was more than one tag. 267 | * Is undefined if not known. 268 | */ 269 | sinceTags?: string[]; 270 | 271 | /** 272 | * Whether this is a proposed notification. If omitted 273 | * the notification is final. 274 | */ 275 | proposed?: boolean; 276 | 277 | /** 278 | * Whether the notification is deprecated or not. If deprecated 279 | * the property contains the deprecation message. 280 | */ 281 | deprecated?: string; 282 | 283 | /** 284 | * The client capability property path if any. 285 | */ 286 | clientCapability?: string; 287 | 288 | /** 289 | * The server capability property path if any. 290 | */ 291 | serverCapability?: string; 292 | }; 293 | 294 | /** 295 | * Represents an object property. 296 | */ 297 | export type Property = { 298 | /** 299 | * The property name; 300 | */ 301 | name: string; 302 | 303 | /** 304 | * The type of the property 305 | */ 306 | type: Type; 307 | 308 | /** 309 | * Whether the property is optional. If 310 | * omitted, the property is mandatory. 311 | */ 312 | optional?: boolean; 313 | 314 | /** 315 | * An optional documentation. 316 | */ 317 | documentation?: string; 318 | 319 | /** 320 | * Since when (release number) this property is 321 | * available. Is undefined if not known. 322 | */ 323 | since?: string; 324 | 325 | /** 326 | * All since tags in case there was more than one tag. 327 | * Is undefined if not known. 328 | */ 329 | sinceTags?: string[]; 330 | 331 | /** 332 | * Whether this is a proposed property. If omitted, 333 | * the structure is final. 334 | */ 335 | proposed?: boolean; 336 | 337 | /** 338 | * Whether the property is deprecated or not. If deprecated 339 | * the property contains the deprecation message. 340 | */ 341 | deprecated?: string; 342 | }; 343 | 344 | /** 345 | * Defines the structure of an object literal. 346 | */ 347 | export type Structure = { 348 | /** 349 | * The name of the structure. 350 | */ 351 | name: string; 352 | 353 | /** 354 | * Structures extended from. This structures form 355 | * a polymorphic type hierarchy. 356 | */ 357 | extends?: Type[]; 358 | 359 | /** 360 | * Structures to mix in. The properties of these 361 | * structures are `copied` into this structure. 362 | * Mixins don't form a polymorphic type hierarchy in 363 | * LSP. 364 | */ 365 | mixins?: Type[]; 366 | 367 | /** 368 | * The properties. 369 | */ 370 | properties: Property[]; 371 | 372 | /** 373 | * An optional documentation; 374 | */ 375 | documentation?: string; 376 | 377 | /** 378 | * Since when (release number) this structure is 379 | * available. Is undefined if not known. 380 | */ 381 | since?: string; 382 | 383 | /** 384 | * All since tags in case there was more than one tag. 385 | * Is undefined if not known. 386 | */ 387 | sinceTags?: string[]; 388 | 389 | /** 390 | * Whether this is a proposed structure. If omitted, 391 | * the structure is final. 392 | */ 393 | proposed?: boolean; 394 | 395 | /** 396 | * Whether the structure is deprecated or not. If deprecated 397 | * the property contains the deprecation message. 398 | */ 399 | deprecated?: string; 400 | }; 401 | 402 | /** 403 | * Defines an unnamed structure of an object literal. 404 | */ 405 | export type StructureLiteral = { 406 | 407 | /** 408 | * The properties. 409 | */ 410 | properties: Property[]; 411 | 412 | /** 413 | * An optional documentation. 414 | */ 415 | documentation?: string; 416 | 417 | /** 418 | * Since when (release number) this structure is 419 | * available. Is undefined if not known. 420 | */ 421 | since?: string; 422 | 423 | /** 424 | * All since tags in case there was more than one tag. 425 | * Is undefined if not known. 426 | */ 427 | sinceTags?: string[]; 428 | 429 | /** 430 | * Whether this is a proposed structure. If omitted, 431 | * the structure is final. 432 | */ 433 | proposed?: boolean; 434 | 435 | /** 436 | * Whether the literal is deprecated or not. If deprecated 437 | * the property contains the deprecation message. 438 | */ 439 | deprecated?: string; 440 | }; 441 | 442 | /** 443 | * Defines a type alias. 444 | * (e.g. `type Definition = Location | LocationLink`) 445 | */ 446 | export type TypeAlias = { 447 | /** 448 | * The name of the type alias. 449 | */ 450 | name: string; 451 | 452 | /** 453 | * The aliased type. 454 | */ 455 | type: Type; 456 | 457 | /** 458 | * An optional documentation. 459 | */ 460 | documentation?: string; 461 | 462 | /** 463 | * Since when (release number) this structure is 464 | * available. Is undefined if not known. 465 | */ 466 | since?: string; 467 | 468 | /** 469 | * All since tags in case there was more than one tag. 470 | * Is undefined if not known. 471 | */ 472 | sinceTags?: string[]; 473 | 474 | /** 475 | * Whether this is a proposed type alias. If omitted, 476 | * the type alias is final. 477 | */ 478 | proposed?: boolean; 479 | 480 | /** 481 | * Whether the type alias is deprecated or not. If deprecated 482 | * the property contains the deprecation message. 483 | */ 484 | deprecated?: string; 485 | }; 486 | 487 | /** 488 | * Defines an enumeration entry. 489 | */ 490 | export type EnumerationEntry = { 491 | /** 492 | * The name of the enum item. 493 | */ 494 | name: string; 495 | 496 | /** 497 | * The value. 498 | */ 499 | value: string | number; 500 | 501 | /** 502 | * An optional documentation. 503 | */ 504 | documentation?: string; 505 | 506 | /** 507 | * Since when (release number) this enumeration entry is 508 | * available. Is undefined if not known. 509 | */ 510 | since?: string; 511 | 512 | /** 513 | * All since tags in case there was more than one tag. 514 | * Is undefined if not known. 515 | */ 516 | sinceTags?: string[]; 517 | 518 | /** 519 | * Whether this is a proposed enumeration entry. If omitted, 520 | * the enumeration entry is final. 521 | */ 522 | proposed?: boolean; 523 | 524 | /** 525 | * Whether the enum entry is deprecated or not. If deprecated 526 | * the property contains the deprecation message. 527 | */ 528 | deprecated?: string; 529 | }; 530 | 531 | export type EnumerationType = { kind: 'base'; name: 'string' | 'integer' | 'uinteger' }; 532 | 533 | /** 534 | * Defines an enumeration. 535 | */ 536 | export type Enumeration = { 537 | /** 538 | * The name of the enumeration. 539 | */ 540 | name: string; 541 | 542 | /** 543 | * The type of the elements. 544 | */ 545 | type: EnumerationType; 546 | 547 | /** 548 | * The enum values. 549 | */ 550 | values: EnumerationEntry[]; 551 | 552 | /** 553 | * Whether the enumeration supports custom values (e.g. values which are not 554 | * part of the set defined in `values`). If omitted no custom values are 555 | * supported. 556 | */ 557 | supportsCustomValues?: boolean; 558 | 559 | /** 560 | * An optional documentation. 561 | */ 562 | documentation?: string; 563 | 564 | /** 565 | * Since when (release number) this enumeration is 566 | * available. Is undefined if not known. 567 | */ 568 | since?: string; 569 | 570 | /** 571 | * All since tags in case there was more than one tag. 572 | * Is undefined if not known. 573 | */ 574 | sinceTags?: string[]; 575 | 576 | /** 577 | * Whether this is a proposed enumeration. If omitted, 578 | * the enumeration is final. 579 | */ 580 | proposed?: boolean; 581 | 582 | /** 583 | * Whether the enumeration is deprecated or not. If deprecated 584 | * the property contains the deprecation message. 585 | */ 586 | deprecated?: string; 587 | }; 588 | 589 | export type MetaData = { 590 | /** 591 | * The protocol version. 592 | */ 593 | version: string; 594 | }; 595 | 596 | /** 597 | * The actual meta model. 598 | */ 599 | export type MetaModel = { 600 | /** 601 | * Additional meta data. 602 | */ 603 | metaData: MetaData; 604 | 605 | /** 606 | * The requests. 607 | */ 608 | requests: Request[]; 609 | 610 | /** 611 | * The notifications. 612 | */ 613 | notifications: Notification[]; 614 | 615 | /** 616 | * The structures. 617 | */ 618 | structures: Structure[]; 619 | 620 | /** 621 | * The enumerations. 622 | */ 623 | enumerations: Enumeration[]; 624 | 625 | /** 626 | * The type aliases. 627 | */ 628 | typeAliases: TypeAlias[]; 629 | }; 630 | -------------------------------------------------------------------------------- /src/app.ts: -------------------------------------------------------------------------------- 1 | 2 | import { LspClient, LspClientImpl } from "./lsp"; 3 | import { createMcp, startMcp } from "./mcp"; 4 | import { 5 | CallToolRequestSchema, 6 | ListToolsRequestSchema, 7 | } from "@modelcontextprotocol/sdk/types.js"; 8 | import { getLspMethods, lspMethodHandler, LSPMethods, openFileContents } from "./lsp-methods"; 9 | import { ToolManager } from "./tool-manager"; 10 | import { Logger } from "vscode-jsonrpc"; 11 | import { Config } from "./config"; 12 | import { Server as McpServer } from "@modelcontextprotocol/sdk/server/index.js"; 13 | import { JSONSchema4, JSONSchema4TypeName } from "json-schema"; 14 | import { LspManager } from "./lsp-manager"; 15 | 16 | export class App { 17 | private readonly toolManager: ToolManager; 18 | private readonly lspManager: LspManager; 19 | private readonly mcp: McpServer; 20 | private readonly availableMethodIds: Promise; 21 | private readonly workspace: string; 22 | 23 | constructor( 24 | config: Config, 25 | protected readonly logger: Logger, 26 | ) { 27 | // keeps track of all the tools we're sending to the MCP 28 | this.toolManager = new ToolManager(logger); 29 | // keeps track of all the LSP Clients we're using 30 | this.lspManager = new LspManager(this.buildLsps(config.lsps, logger)); 31 | // the MCP server 32 | this.mcp = createMcp(); 33 | // The LSP methods we support (textDocument/foo, etc) 34 | this.availableMethodIds = getLspMethods(config.methods); 35 | 36 | this.workspace = config.workspace ?? "/"; 37 | 38 | // Cleanup on any signal 39 | process.on('SIGINT', () => this.dispose()); 40 | process.on('SIGTERM', () => this.dispose()); 41 | process.on('exit', () => this.dispose()); 42 | } 43 | 44 | private async initializeMcp() { 45 | this.mcp.setRequestHandler(ListToolsRequestSchema, async () => { 46 | const mcpTools = this.toolManager.getTools().map((tool) => ({ 47 | name: tool.id, 48 | description: tool.description, 49 | inputSchema: tool.inputSchema, 50 | })); 51 | 52 | return { 53 | tools: mcpTools 54 | }; 55 | }); 56 | 57 | this.mcp.setRequestHandler(CallToolRequestSchema, async (request) => { 58 | const { name, arguments: args } = request.params; 59 | if (!args) { 60 | throw new Error("No arguments"); 61 | } 62 | 63 | const result = await this.toolManager.callTool(name, args); 64 | const serialized = 65 | typeof result === "string" ? result : JSON.stringify(result, null, 2); 66 | 67 | return { 68 | content: [{ type: "text", text: serialized }], 69 | }; 70 | }); 71 | } 72 | 73 | private async registerTools() { 74 | this.toolManager.registerTool({ 75 | id: "lsp_info", 76 | description: "Returns information about the the LSP tools available. This is useful for debugging which programming languages are supported.", 77 | inputSchema: { 78 | type: "object" as "object", 79 | }, 80 | handler: async () => { 81 | const result = this.lspManager.getLsps().map((lsp) => { 82 | const started = lsp.isStarted(); 83 | return { 84 | id: lsp.id, 85 | languages: lsp.languages, 86 | extensions: lsp.extensions, 87 | // Remember, this is communicating with an AI. It doesn't care about type safety 88 | started: started 89 | ? true 90 | : `Not started. LSP will start automatically when needed, such as when analyzing a file with extensions ${lsp.extensions.join(", ")}.`, 91 | capabilities: started 92 | ? lsp.capabilities 93 | : "LSP not started. Capabilities will be available when started.", 94 | }; 95 | }); 96 | 97 | return JSON.stringify(result, null, 2) 98 | }, 99 | }); 100 | 101 | this.toolManager.registerTool({ 102 | id: "file_contents_to_uri", 103 | description: 104 | `Creates a URI given some file contents to be used in the LSP methods that require a URI. This is only required if the file is not on the filesystem. Otherwise you may pass the file path directly.`, 105 | inputSchema: { 106 | type: "object" as "object", 107 | properties: { 108 | file_contents: { 109 | type: "string", 110 | description: "The contents of the file", 111 | }, 112 | programming_language: { 113 | type: "string", 114 | description: "The programming language of the file", 115 | }, 116 | }, 117 | required: ["file_contents"], 118 | }, 119 | handler: async (args) => { 120 | const { file_contents, programming_language } = args; 121 | const lsp = this.lspManager.getLspByLanguage(programming_language) || this.lspManager.getDefaultLsp(); 122 | const uri = `mem://${Math.random().toString(36).substring(2, 15)}.${lsp.id}`; 123 | if (!lsp) { 124 | throw new Error(`No LSP found for language: ${programming_language}`); 125 | } 126 | 127 | await openFileContents(lsp, uri, file_contents); 128 | 129 | return uri; 130 | }, 131 | }); 132 | 133 | const availableMethodIds = (await this.availableMethodIds).sort((a, b) => a.id.localeCompare(b.id)); 134 | const lsps = this.lspManager.getLsps(); 135 | const lspProperty: JSONSchema4 | undefined = lsps.length > 1 ? { 136 | type: "string", 137 | name: "lsp", 138 | description: "The LSP to use to execute this method. Options are: " + 139 | lsps.map((lsp) => ` ${lsp.id} for the programming languages ${lsp.languages.join(", ")}`).join("\n"), 140 | enum: lsps.map((lsp) => lsp.id) 141 | } : undefined; 142 | 143 | availableMethodIds.forEach((method) => { 144 | const id = method.id; 145 | 146 | // Clean up the input schema a bit 147 | const inputSchema: JSONSchema4 = this.removeInputSchemaInvariants(method.inputSchema); 148 | if (inputSchema.properties) { 149 | for (const [propertyKey, property] of Object.entries(inputSchema.properties)) { 150 | if (["partialResultToken", "workDoneToken"].includes(propertyKey)) { 151 | if (!inputSchema.required || !Array.isArray(inputSchema.required) || !inputSchema.required.includes(propertyKey)) { 152 | delete inputSchema.properties[propertyKey]; 153 | } 154 | } 155 | } 156 | } 157 | 158 | // If we're set up with more than one LSP, we'll request the LSP to be optionally specified 159 | // If it isn't specified, we'll have to use some logic to figure out which LSP to use 160 | if (lspProperty && inputSchema.properties) { 161 | inputSchema.properties[lspProperty.name] = lspProperty; 162 | } 163 | 164 | this.toolManager.registerTool({ 165 | id: method.id.replace("/", "_"), 166 | description: method.description, 167 | inputSchema: inputSchema, 168 | handler: (args) => { 169 | let lsp: LspClient | undefined; 170 | if (lspProperty) { 171 | const lspId = args[lspProperty.name]; 172 | if (lspId) { 173 | lsp = this.lspManager.getLsp(lspId); 174 | if (!lsp) { 175 | // Sometimes the LLM gets confused and specifies the language instead of the LSP ID 176 | lsp = this.lspManager.getLspByLanguage(lspId); 177 | } 178 | } 179 | 180 | if (!lsp && args.textDocument?.uri) { 181 | // try by file extension 182 | const extension = args.textDocument.uri.split(".").pop(); 183 | if (extension) { 184 | lsp = this.lspManager.getLspByExtension(extension); 185 | } 186 | } 187 | } 188 | 189 | // I wonder if using the last used LSP would be a better default... 190 | if (!lsp) { 191 | lsp = this.lspManager.getDefaultLsp(); 192 | } 193 | 194 | return lspMethodHandler(lsp, id, args); 195 | }, 196 | }); 197 | }); 198 | } 199 | 200 | public async start() { 201 | await this.registerTools(), 202 | await this.initializeMcp(), 203 | 204 | await startMcp(this.mcp); 205 | } 206 | 207 | public async dispose() { 208 | if (this.lspManager !== undefined) { 209 | this.lspManager.getLsps().forEach((lsp) => lsp.dispose()); 210 | } 211 | 212 | if (this.mcp !== undefined) { 213 | await this.mcp.close(); 214 | } 215 | } 216 | 217 | private async getAvailableMethodIds() { 218 | return this.availableMethodIds; 219 | } 220 | 221 | // Remove invariant types from the input schema since some MCPs have a hard time with them 222 | // Looking at you mcp-client-cli 223 | private removeInputSchemaInvariants(inputSchema: JSONSchema4): JSONSchema4 { 224 | let type = inputSchema.type; 225 | if (type && Array.isArray(type)) { 226 | if (type.length === 1) { 227 | type = type[0] as JSONSchema4TypeName; 228 | } else if (type.includes('string')) { 229 | type = 'string' as JSONSchema4TypeName; 230 | } else { 231 | // guess 232 | type = type[0] as JSONSchema4TypeName; 233 | } 234 | } 235 | return { 236 | ...inputSchema, 237 | type: type, 238 | properties: inputSchema.properties 239 | ? Object.fromEntries( 240 | Object.entries(inputSchema.properties).map(([key, value]) => [ 241 | key, 242 | this.removeInputSchemaInvariants(value), 243 | ]), 244 | ) 245 | : undefined, 246 | }; 247 | } 248 | 249 | private buildLsps(lspConfigs: Config["lsps"], logger: Logger): LspClient[] { 250 | return lspConfigs.map( 251 | (lspConfig) => 252 | new LspClientImpl( 253 | lspConfig.id, 254 | lspConfig.languages, 255 | lspConfig.extensions, 256 | this.workspace, 257 | lspConfig.command, 258 | lspConfig.args, 259 | logger, 260 | ), 261 | ); 262 | } 263 | } 264 | -------------------------------------------------------------------------------- /src/config.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | import fs from "fs/promises"; 3 | 4 | const ConfigSchema = z.object({ 5 | lsps: z.array(z.object({ 6 | id: z.string(), 7 | extensions: z.array(z.string()), 8 | languages: z.array(z.string()), 9 | command: z.string(), 10 | args: z.array(z.string()), 11 | })), 12 | methods: z.optional(z.array(z.string()), { 13 | description: "LSP methods to enable, if not provided, all methods will be enabled", 14 | }), 15 | workspace: z.optional(z.string(), { 16 | description: "Path to the workspace to use for the LSP. Defaults to /" 17 | }), 18 | }); 19 | 20 | export type Config = z.infer; 21 | 22 | export async function loadConfig(path: string): Promise { 23 | const stripJsonComments = await import("strip-json-comments"); 24 | const contents = await fs.readFile(path, "utf8"); 25 | const config = stripJsonComments.default(contents); 26 | 27 | return await ConfigSchema.parseAsync(JSON.parse(config)); 28 | } 29 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { nullLogger, errorLogger } from "./logger"; 4 | import { Command, OptionValues } from "commander"; 5 | import { Config, loadConfig } from "./config"; 6 | import { App } from "./app"; 7 | import { Logger } from "vscode-languageserver-protocol"; 8 | 9 | async function buildConfig(options: OptionValues, logger: Logger): Promise { 10 | let config: Config | undefined; 11 | 12 | if (options.config) { 13 | try { 14 | config = await loadConfig(options.config); 15 | } catch (e) { 16 | logger.error(`Failed to parse config file ${options.config}`); 17 | process.exit(1); 18 | } 19 | 20 | if (config === undefined) { 21 | logger.error(`Failed to parse config file ${options.config}`); 22 | process.exit(1); 23 | } 24 | } else { 25 | if (!options.lsp) { 26 | logger.error("No LSP command provided"); 27 | process.exit(1); 28 | } 29 | 30 | config = { 31 | lsps: [ 32 | { 33 | id: "lsp", 34 | extensions: [], 35 | languages: [], 36 | command: "sh", 37 | args: ["-c", options.lsp], 38 | }, 39 | ] 40 | }; 41 | } 42 | 43 | if (options.methods) { 44 | config.methods = options.methods; 45 | } 46 | 47 | if (options.workspace) { 48 | config.workspace = options.workspace; 49 | } 50 | 51 | return config; 52 | } 53 | 54 | async function main() { 55 | const program = new Command(); 56 | 57 | program 58 | .name("lsp-mcp") 59 | .description("A tool for providing LSP requests to MCP") 60 | .version("0.1.0") 61 | .option( 62 | "-m, --methods [string...]", 63 | "LSP methods to enabled (Default: all)", 64 | ) 65 | .option( 66 | "-l, --lsp ", 67 | "LSP command to start (note: command is passed through sh -c)", 68 | ) 69 | .option( 70 | "-w, --workspace [string]", 71 | "Path to the workspace to use for the LSP. Defaults to /" 72 | ) 73 | .option("-v, --verbose", "Verbose output (Dev only, don't use with MCP)") 74 | .option("-c, --config [string]", "Path to config file") 75 | .parse(process.argv); 76 | 77 | const options = program.opts(); 78 | 79 | // UGH i really need to start using a proper logging lib 80 | const logger = options.verbose ? errorLogger : nullLogger; 81 | logger.info(`Running with: ${JSON.stringify(options)}`); 82 | 83 | const config = await buildConfig(options, logger); 84 | const app = new App(config, logger); 85 | 86 | try { 87 | await app.start(); 88 | } catch (e: any) { 89 | logger.error(e.toString?.()); 90 | process.exit(1); 91 | } 92 | } 93 | 94 | main(); 95 | -------------------------------------------------------------------------------- /src/logger.ts: -------------------------------------------------------------------------------- 1 | import { Logger } from "vscode-jsonrpc"; 2 | 3 | function formatMessage(message: string) { 4 | if (!message.endsWith("\n")) { 5 | message += "\n"; 6 | } 7 | 8 | return message; 9 | } 10 | 11 | export const errorLogger: Logger = { 12 | error: (message: string) => { 13 | console.error(formatMessage(message)); 14 | }, 15 | warn: (message: string) => { 16 | console.warn(formatMessage(message)); 17 | }, 18 | info: (message: string) => { 19 | console.info(formatMessage(message)); 20 | }, 21 | log: (message: string) => { 22 | console.log(formatMessage(message)); 23 | }, 24 | }; 25 | 26 | export const consoleLogger: Logger = { 27 | error: (message: string) => { 28 | console.error(formatMessage(message)); 29 | }, 30 | warn: (message: string) => { 31 | console.warn(formatMessage(message)); 32 | }, 33 | info: (message: string) => { 34 | console.info(formatMessage(message)); 35 | }, 36 | log: (message: string) => { 37 | console.log(formatMessage(message)); 38 | }, 39 | }; 40 | 41 | export const nullLogger: Logger = { 42 | error: (message: string) => { 43 | }, 44 | warn: (message: string) => { 45 | }, 46 | info: (message: string) => { 47 | }, 48 | log: (message: string) => { 49 | }, 50 | }; 51 | -------------------------------------------------------------------------------- /src/lsp-manager.ts: -------------------------------------------------------------------------------- 1 | import { LspClient } from "./lsp"; 2 | 3 | export class LspManager { 4 | private readonly lsps: Map; 5 | private readonly languageToLsp: Map; 6 | private readonly extensionToLsp: Map; 7 | private readonly defaultLsp: LspClient; 8 | 9 | constructor(lsps: LspClient[]) { 10 | this.defaultLsp = lsps[0]; 11 | this.lsps = new Map(lsps.map((lsp) => [lsp.id, lsp])); 12 | 13 | // Build language lookup map 14 | this.languageToLsp = new Map(); 15 | this.extensionToLsp = new Map(); 16 | for (const lsp of lsps) { 17 | for (const language of lsp.languages) { 18 | // TODO: handle conflict 19 | this.languageToLsp.set(language.toLowerCase(), lsp); 20 | } 21 | 22 | for (const extension of lsp.extensions) { 23 | // TODO: handle conflict 24 | this.extensionToLsp.set(extension.toLowerCase(), lsp); 25 | } 26 | 27 | this.extensionToLsp.set(lsp.id, lsp); 28 | } 29 | } 30 | 31 | getLsp(id: string): LspClient | undefined { 32 | return this.lsps.get(id.toLowerCase()); 33 | } 34 | 35 | getLsps(): LspClient[] { 36 | return Array.from(this.lsps.values()); 37 | } 38 | 39 | getLspByLanguage(language: string): LspClient | undefined { 40 | return this.languageToLsp.get(language.toLowerCase()); 41 | } 42 | 43 | getLspByExtension(extension: string): LspClient | undefined { 44 | return this.extensionToLsp.get(extension.toLowerCase()); 45 | } 46 | 47 | getDefaultLsp(): LspClient { 48 | return this.defaultLsp; 49 | } 50 | 51 | hasManyLsps(): boolean { 52 | return this.lsps.size > 1; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/lsp-methods.ts: -------------------------------------------------------------------------------- 1 | import * as protocol from "vscode-languageserver-protocol"; 2 | import * as path from "path"; 3 | import * as fs from "fs/promises"; 4 | import { LspClient } from "./lsp"; 5 | import $RefParser from "@apidevtools/json-schema-ref-parser"; 6 | import { JSONSchema4 } from "json-schema"; 7 | import { MetaModel } from "./3rdparty/metaModel"; 8 | 9 | // List of LSP requests that we do not want to expose 10 | const toolBlacklist = [ 11 | // These are handled by this program 12 | "initialize", 13 | "shutdown", 14 | 15 | // Useless for MCP? 16 | "client/registerCapability", 17 | "client/unregisterCapability", 18 | ]; 19 | 20 | export interface LSPMethods { 21 | id: string; 22 | description: string; 23 | inputSchema: JSONSchema4; 24 | } 25 | 26 | // Converts /path/to/file to file:///path/to/file 27 | function pathToFileUri(path: string): string { 28 | return `file://${path}` 29 | } 30 | 31 | // convert file:///path/to/file to /path/to/file 32 | function fileUriToPath(uri: string): string { 33 | if (uri.startsWith("file://")) { 34 | return path.resolve(uri.slice(7)); 35 | } 36 | 37 | return path.resolve(uri); 38 | } 39 | 40 | // Let's the LSP know about a file contents 41 | export async function openFileContents(lsp: LspClient, uri: string, contents: string): Promise { 42 | await lsp.sendNotification(protocol.DidOpenTextDocumentNotification.method, { 43 | textDocument: { 44 | uri: uri, 45 | languageId: "typescript", 46 | version: 1, 47 | text: contents, 48 | }, 49 | }); 50 | } 51 | 52 | // Let's the LSP know about a file 53 | async function openFile(lsp: LspClient, file: string, uri: string): Promise { 54 | const contents = await fs.readFile(file, "utf8"); 55 | await openFileContents(lsp, uri, contents); 56 | } 57 | 58 | export async function lspMethodHandler(lsp: LspClient, methodId: string, args: Record): Promise { 59 | let lspArgs = args; 60 | // For uris, we need to tell the LSP about the file contents 61 | // This helper makes the LLM's work easier (and less likely to break) by not requiring the LLM to have to handle opening files itself 62 | // However, don't handle mem:// files as they are special in that they are not actual files on disk 63 | if (lspArgs.textDocument?.uri && !lspArgs.textDocument.uri.startsWith("mem://")) { 64 | const file = fileUriToPath(lspArgs.textDocument.uri); 65 | const uri = pathToFileUri(file); 66 | // TODO: decide how to close the file. Timeout I think is the best option? 67 | await openFile(lsp, file, uri); 68 | lspArgs = { ...lspArgs, textDocument: { ...lspArgs.textDocument, uri } }; 69 | } 70 | 71 | return await lsp.sendRequest(methodId, lspArgs); 72 | }; 73 | 74 | async function getMetaModel() { 75 | const metaModelString = await fs.readFile( 76 | path.join(__dirname, "resources", "metaModel.json"), 77 | "utf8" 78 | ); 79 | return JSON.parse(metaModelString) as MetaModel; 80 | } 81 | 82 | async function getDereferencedJsonSchema() { 83 | const parser = new $RefParser() 84 | const schema = await parser.parse(path.join(__dirname,"./resources/generated.protocol.schema.json")) 85 | 86 | const dereferenced = await parser.dereference(schema, { 87 | mutateInputSchema: false, 88 | }) 89 | 90 | if (!dereferenced.definitions) { 91 | throw new Error("No definitions") 92 | } 93 | 94 | return dereferenced as { definitions: Record }; 95 | } 96 | 97 | let methods: LSPMethods[] | undefined = undefined; 98 | 99 | export async function getLspMethods( 100 | allowedMethodIds: string[] | undefined = undefined 101 | ): Promise { 102 | // technically this could do work twice if it's called asynchronously, but it's not a big deal 103 | if (methods !== undefined) { 104 | return methods; 105 | } 106 | 107 | const metaModel = await getMetaModel(); 108 | const metaModelLookup = new Map(metaModel.requests.map((request) => [request.method, request])) 109 | 110 | const jsonSchema = await getDereferencedJsonSchema(); 111 | const jsonSchemaLookup = new Map( 112 | Object.values(jsonSchema.definitions) 113 | .filter(definition => definition.properties?.method?.enum?.length === 1) 114 | .map(definition => [ 115 | String(definition.properties?.method?.enum?.[0]), 116 | definition 117 | ]) 118 | ); 119 | 120 | const methodIds = allowedMethodIds ?? metaModel.requests.map((request) => request.method).filter((id) => !toolBlacklist.includes(id)); 121 | 122 | methods = methodIds.map((id) => { 123 | const definition = jsonSchemaLookup.get(id) 124 | // TODO: Because I've sourced the jsonapi and the metamodel from different sources, they aren't always in sync. 125 | // In the case when I don't have a jsonschema, I'll just skip for now 126 | if (!definition?.properties) { 127 | return undefined; 128 | } 129 | 130 | // TODO: Not sure if this is the best way to handle this 131 | // But this occurs when the jsonschema has no param properties 132 | let inputSchema = definition.properties.params 133 | if (!inputSchema || !inputSchema.type) { 134 | inputSchema = { 135 | type: 'object' as 'object', 136 | } 137 | } 138 | 139 | return { 140 | id: id, 141 | description: `method: ${id}\n${metaModelLookup.get(id)?.documentation ?? ""}`, 142 | inputSchema: inputSchema, 143 | } 144 | }).filter((tool) => tool !== undefined); 145 | 146 | return methods 147 | } 148 | -------------------------------------------------------------------------------- /src/lsp.ts: -------------------------------------------------------------------------------- 1 | import { ChildProcess, spawn } from "child_process"; 2 | import * as rpc from "vscode-jsonrpc"; 3 | import { StreamMessageReader, StreamMessageWriter } from "vscode-jsonrpc/node"; 4 | import { InitializeRequest } from "vscode-languageserver-protocol"; 5 | import * as protocol from "vscode-languageserver-protocol"; 6 | import { Logger } from "vscode-jsonrpc"; 7 | import path from "path"; 8 | 9 | export interface LspClient { 10 | id: string; 11 | languages: string[]; 12 | extensions: string[]; 13 | capabilities: protocol.ServerCapabilities | undefined; 14 | start(): Promise; 15 | isStarted(): boolean; 16 | dispose: () => void; 17 | sendRequest(method: string, args: any): Promise; 18 | sendNotification(method: string, args: any): Promise; 19 | } 20 | 21 | export class LspClientImpl implements LspClient { 22 | 23 | protected childProcess: ChildProcess | undefined; 24 | 25 | protected connection: rpc.MessageConnection | undefined; 26 | 27 | public capabilities: protocol.ServerCapabilities | undefined; 28 | 29 | public constructor( 30 | public readonly id: string, 31 | public readonly languages: string[], 32 | public readonly extensions: string[], 33 | public readonly workspace: string, 34 | private readonly command: string, 35 | private readonly args: string[], 36 | private readonly logger: Logger, // TODO: better long term solution for logging 37 | ) { 38 | this.capabilities = undefined; 39 | } 40 | 41 | public async start() { 42 | // TODO: This should return a promise if the LSP is still starting 43 | // Just don't call start() twice and it'll be fine :) 44 | if (this.isStarted()) { 45 | return; 46 | } 47 | 48 | const childProcess = this.childProcess = spawn(this.command, this.args); 49 | 50 | if (!childProcess.stdout || !childProcess.stdin) { 51 | throw new Error("Child process not started"); 52 | } 53 | 54 | const connection = this.connection = rpc.createMessageConnection( 55 | new StreamMessageReader(childProcess.stdout), 56 | new StreamMessageWriter(childProcess.stdin), 57 | this.logger, 58 | ); 59 | 60 | connection.onError((error) => { 61 | this.logger.error(`Connection error: ${error}`); 62 | childProcess.kill(); 63 | }); 64 | 65 | connection.onClose(() => { 66 | this.logger.log("Connection closed"); 67 | childProcess.kill(); 68 | }); 69 | 70 | connection.onUnhandledNotification((notification) => { 71 | this.logger.log(`Unhandled notification: ${JSON.stringify(notification)}`); 72 | }); 73 | 74 | connection.listen(); 75 | 76 | // TODO: We should figure out how to specify the capabilities we want 77 | const capabilities: protocol.ClientCapabilities = {}; 78 | 79 | const uri = `file://${this.workspace}`; 80 | const response = await connection.sendRequest(InitializeRequest.type, { 81 | processId: process.pid, 82 | rootUri: uri, 83 | capabilities: capabilities, 84 | }); 85 | 86 | this.logger.info(`Server LSP capabilities: ${JSON.stringify(response, null, 2)}`); 87 | this.capabilities = response.capabilities; 88 | } 89 | 90 | public isStarted(): this is LspClientImpl & { connection: rpc.MessageConnection } { 91 | return !!this.connection; 92 | } 93 | 94 | private assertStarted(): asserts this is LspClientImpl & { connection: rpc.MessageConnection } { 95 | if (!this.connection) { 96 | throw new Error("Not started"); 97 | } 98 | } 99 | 100 | async sendRequest(method: string, args: any): Promise { 101 | if (!this.isStarted()) { 102 | await this.start(); 103 | } 104 | 105 | this.assertStarted(); 106 | 107 | return await this.connection.sendRequest(method, args); 108 | } 109 | 110 | async sendNotification(method: string, args: any): Promise { 111 | if (!this.isStarted()) { 112 | await this.start(); 113 | } 114 | 115 | this.assertStarted(); 116 | 117 | return await this.connection.sendNotification(method, args); 118 | } 119 | 120 | dispose() { 121 | try { 122 | this.connection?.dispose(); 123 | this.childProcess?.kill(); 124 | } catch (e: any) { 125 | this.logger.error(e.toString?.()); 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/mcp.ts: -------------------------------------------------------------------------------- 1 | import { Server as McpServer } from "@modelcontextprotocol/sdk/server/index.js"; 2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; 3 | 4 | // Create an MCP server 5 | export function createMcp(): McpServer { 6 | return new McpServer( 7 | { 8 | name: "LSP", 9 | version: "0.1.0", 10 | }, 11 | { 12 | capabilities: { 13 | tools: {}, 14 | }, 15 | }, 16 | ); 17 | } 18 | 19 | // Start receiving messages on stdin and sending messages on stdout 20 | export async function startMcp(mcp: McpServer) { 21 | const transport = new StdioServerTransport(); 22 | await mcp.connect(transport); 23 | } 24 | -------------------------------------------------------------------------------- /src/tool-manager.ts: -------------------------------------------------------------------------------- 1 | import { JSONSchema4 } from "json-schema"; 2 | import { Logger } from "vscode-languageserver-protocol"; 3 | 4 | export interface Tool { 5 | id: string; 6 | description: string; 7 | inputSchema: JSONSchema4; 8 | handler: (args: Record) => Promise; 9 | } 10 | 11 | export class ToolManager { 12 | private toolsById: Map = new Map(); 13 | 14 | constructor(private readonly logger: Logger) {} 15 | 16 | public registerTool(tool: Tool): void { 17 | this.logger.info(`Registering tool ${tool.id}`); 18 | this.toolsById.set(tool.id, tool); 19 | } 20 | 21 | public async callTool(id: string, args: Record): Promise { 22 | const tool = this.getTool(id); 23 | if (!tool) { 24 | throw new Error(`Tool ${id} not found`); 25 | } 26 | return tool.handler(args); 27 | } 28 | 29 | public getTools(): Tool[] { 30 | return Array.from(this.toolsById.values()); 31 | } 32 | 33 | private getTool(id: string): Tool | undefined { 34 | return this.toolsById.get(id); 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "module": "NodeNext", 5 | "strict": true, 6 | "outDir": "dist", 7 | "rootDir": "src", 8 | "esModuleInterop": true, 9 | "skipLibCheck": true, 10 | "forceConsistentCasingInFileNames": true 11 | }, 12 | "include": ["src"] 13 | } 14 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@apidevtools/json-schema-ref-parser@^11.9.1": 6 | version "11.9.1" 7 | resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.9.1.tgz#51d297224f6ee1dab40dfb2dfe298812b8e0ef9c" 8 | integrity sha512-OvyhwtYaWSTfo8NfibmFlgl+pIMaBOmN0OwZ3CPaGscEK3B8FCVDuQ7zgxY8seU/1kfSvNWnyB0DtKJyNLxX7g== 9 | dependencies: 10 | "@jsdevtools/ono" "^7.1.3" 11 | "@types/json-schema" "^7.0.15" 12 | js-yaml "^4.1.0" 13 | 14 | "@cspotcode/source-map-support@^0.8.0": 15 | version "0.8.1" 16 | resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" 17 | integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== 18 | dependencies: 19 | "@jridgewell/trace-mapping" "0.3.9" 20 | 21 | "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": 22 | version "4.4.1" 23 | resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" 24 | integrity sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA== 25 | dependencies: 26 | eslint-visitor-keys "^3.4.3" 27 | 28 | "@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": 29 | version "4.12.1" 30 | resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" 31 | integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== 32 | 33 | "@eslint/config-array@^0.19.2": 34 | version "0.19.2" 35 | resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.19.2.tgz#3060b809e111abfc97adb0bb1172778b90cb46aa" 36 | integrity sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w== 37 | dependencies: 38 | "@eslint/object-schema" "^2.1.6" 39 | debug "^4.3.1" 40 | minimatch "^3.1.2" 41 | 42 | "@eslint/core@^0.12.0": 43 | version "0.12.0" 44 | resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.12.0.tgz#5f960c3d57728be9f6c65bd84aa6aa613078798e" 45 | integrity sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg== 46 | dependencies: 47 | "@types/json-schema" "^7.0.15" 48 | 49 | "@eslint/eslintrc@^3.3.0": 50 | version "3.3.0" 51 | resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.0.tgz#96a558f45842989cca7ea1ecd785ad5491193846" 52 | integrity sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ== 53 | dependencies: 54 | ajv "^6.12.4" 55 | debug "^4.3.2" 56 | espree "^10.0.1" 57 | globals "^14.0.0" 58 | ignore "^5.2.0" 59 | import-fresh "^3.2.1" 60 | js-yaml "^4.1.0" 61 | minimatch "^3.1.2" 62 | strip-json-comments "^3.1.1" 63 | 64 | "@eslint/js@9.21.0": 65 | version "9.21.0" 66 | resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.21.0.tgz#4303ef4e07226d87c395b8fad5278763e9c15c08" 67 | integrity sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw== 68 | 69 | "@eslint/object-schema@^2.1.6": 70 | version "2.1.6" 71 | resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" 72 | integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== 73 | 74 | "@eslint/plugin-kit@^0.2.7": 75 | version "0.2.7" 76 | resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz#9901d52c136fb8f375906a73dcc382646c3b6a27" 77 | integrity sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g== 78 | dependencies: 79 | "@eslint/core" "^0.12.0" 80 | levn "^0.4.1" 81 | 82 | "@humanfs/core@^0.19.1": 83 | version "0.19.1" 84 | resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" 85 | integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== 86 | 87 | "@humanfs/node@^0.16.6": 88 | version "0.16.6" 89 | resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.6.tgz#ee2a10eaabd1131987bf0488fd9b820174cd765e" 90 | integrity sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw== 91 | dependencies: 92 | "@humanfs/core" "^0.19.1" 93 | "@humanwhocodes/retry" "^0.3.0" 94 | 95 | "@humanwhocodes/module-importer@^1.0.1": 96 | version "1.0.1" 97 | resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" 98 | integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== 99 | 100 | "@humanwhocodes/retry@^0.3.0": 101 | version "0.3.1" 102 | resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a" 103 | integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA== 104 | 105 | "@humanwhocodes/retry@^0.4.2": 106 | version "0.4.2" 107 | resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.2.tgz#1860473de7dfa1546767448f333db80cb0ff2161" 108 | integrity sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ== 109 | 110 | "@isaacs/cliui@^8.0.2": 111 | version "8.0.2" 112 | resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" 113 | integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== 114 | dependencies: 115 | string-width "^5.1.2" 116 | string-width-cjs "npm:string-width@^4.2.0" 117 | strip-ansi "^7.0.1" 118 | strip-ansi-cjs "npm:strip-ansi@^6.0.1" 119 | wrap-ansi "^8.1.0" 120 | wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" 121 | 122 | "@jridgewell/resolve-uri@^3.0.3": 123 | version "3.1.2" 124 | resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" 125 | integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== 126 | 127 | "@jridgewell/sourcemap-codec@^1.4.10": 128 | version "1.5.0" 129 | resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" 130 | integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== 131 | 132 | "@jridgewell/trace-mapping@0.3.9": 133 | version "0.3.9" 134 | resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" 135 | integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== 136 | dependencies: 137 | "@jridgewell/resolve-uri" "^3.0.3" 138 | "@jridgewell/sourcemap-codec" "^1.4.10" 139 | 140 | "@jsdevtools/ono@^7.1.3": 141 | version "7.1.3" 142 | resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" 143 | integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== 144 | 145 | "@modelcontextprotocol/sdk@^1.5.0": 146 | version "1.5.0" 147 | resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.5.0.tgz#4071e768498a286194ec7686ee4c2f6e9647506d" 148 | integrity sha512-IJ+5iVVs8FCumIHxWqpwgkwOzyhtHVKy45s6Ug7Dv0MfRpaYisH8QQ87rIWeWdOzlk8sfhitZ7HCyQZk7d6b8w== 149 | dependencies: 150 | content-type "^1.0.5" 151 | eventsource "^3.0.2" 152 | raw-body "^3.0.0" 153 | zod "^3.23.8" 154 | zod-to-json-schema "^3.24.1" 155 | 156 | "@nodelib/fs.scandir@2.1.5": 157 | version "2.1.5" 158 | resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" 159 | integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== 160 | dependencies: 161 | "@nodelib/fs.stat" "2.0.5" 162 | run-parallel "^1.1.9" 163 | 164 | "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": 165 | version "2.0.5" 166 | resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" 167 | integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== 168 | 169 | "@nodelib/fs.walk@^1.2.3": 170 | version "1.2.8" 171 | resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" 172 | integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== 173 | dependencies: 174 | "@nodelib/fs.scandir" "2.1.5" 175 | fastq "^1.6.0" 176 | 177 | "@pkgr/core@^0.1.0": 178 | version "0.1.1" 179 | resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" 180 | integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== 181 | 182 | "@tsconfig/node10@^1.0.7": 183 | version "1.0.11" 184 | resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" 185 | integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== 186 | 187 | "@tsconfig/node12@^1.0.7": 188 | version "1.0.11" 189 | resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" 190 | integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== 191 | 192 | "@tsconfig/node14@^1.0.0": 193 | version "1.0.3" 194 | resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" 195 | integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== 196 | 197 | "@tsconfig/node16@^1.0.2": 198 | version "1.0.4" 199 | resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" 200 | integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== 201 | 202 | "@types/estree@^1.0.6": 203 | version "1.0.6" 204 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" 205 | integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== 206 | 207 | "@types/json-schema@^7.0.15": 208 | version "7.0.15" 209 | resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" 210 | integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== 211 | 212 | "@types/node@^22.13.5": 213 | version "22.13.5" 214 | resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.5.tgz#23add1d71acddab2c6a4d31db89c0f98d330b511" 215 | integrity sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg== 216 | dependencies: 217 | undici-types "~6.20.0" 218 | 219 | "@typescript-eslint/eslint-plugin@^8.24.1": 220 | version "8.24.1" 221 | resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.24.1.tgz#d104c2a6212304c649105b18af2c110b4a1dd4ae" 222 | integrity sha512-ll1StnKtBigWIGqvYDVuDmXJHVH4zLVot1yQ4fJtLpL7qacwkxJc1T0bptqw+miBQ/QfUbhl1TcQ4accW5KUyA== 223 | dependencies: 224 | "@eslint-community/regexpp" "^4.10.0" 225 | "@typescript-eslint/scope-manager" "8.24.1" 226 | "@typescript-eslint/type-utils" "8.24.1" 227 | "@typescript-eslint/utils" "8.24.1" 228 | "@typescript-eslint/visitor-keys" "8.24.1" 229 | graphemer "^1.4.0" 230 | ignore "^5.3.1" 231 | natural-compare "^1.4.0" 232 | ts-api-utils "^2.0.1" 233 | 234 | "@typescript-eslint/parser@^8.24.1": 235 | version "8.24.1" 236 | resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.24.1.tgz#67965c2d2ddd7eadb2f094c395695db8334ef9a2" 237 | integrity sha512-Tqoa05bu+t5s8CTZFaGpCH2ub3QeT9YDkXbPd3uQ4SfsLoh1/vv2GEYAioPoxCWJJNsenXlC88tRjwoHNts1oQ== 238 | dependencies: 239 | "@typescript-eslint/scope-manager" "8.24.1" 240 | "@typescript-eslint/types" "8.24.1" 241 | "@typescript-eslint/typescript-estree" "8.24.1" 242 | "@typescript-eslint/visitor-keys" "8.24.1" 243 | debug "^4.3.4" 244 | 245 | "@typescript-eslint/scope-manager@8.24.1": 246 | version "8.24.1" 247 | resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.24.1.tgz#1e1e76ec4560aa85077ab36deb9b2bead4ae124e" 248 | integrity sha512-OdQr6BNBzwRjNEXMQyaGyZzgg7wzjYKfX2ZBV3E04hUCBDv3GQCHiz9RpqdUIiVrMgJGkXm3tcEh4vFSHreS2Q== 249 | dependencies: 250 | "@typescript-eslint/types" "8.24.1" 251 | "@typescript-eslint/visitor-keys" "8.24.1" 252 | 253 | "@typescript-eslint/type-utils@8.24.1": 254 | version "8.24.1" 255 | resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.24.1.tgz#99113e1df63d1571309d87eef68967344c78dd65" 256 | integrity sha512-/Do9fmNgCsQ+K4rCz0STI7lYB4phTtEXqqCAs3gZW0pnK7lWNkvWd5iW545GSmApm4AzmQXmSqXPO565B4WVrw== 257 | dependencies: 258 | "@typescript-eslint/typescript-estree" "8.24.1" 259 | "@typescript-eslint/utils" "8.24.1" 260 | debug "^4.3.4" 261 | ts-api-utils "^2.0.1" 262 | 263 | "@typescript-eslint/types@8.24.1": 264 | version "8.24.1" 265 | resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.24.1.tgz#8777a024f3afc4ace5e48f9a804309c6dd38f95a" 266 | integrity sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A== 267 | 268 | "@typescript-eslint/typescript-estree@8.24.1": 269 | version "8.24.1" 270 | resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.24.1.tgz#3bb479401f8bd471b3c6dd3db89e7256977c54db" 271 | integrity sha512-UPyy4MJ/0RE648DSKQe9g0VDSehPINiejjA6ElqnFaFIhI6ZEiZAkUI0D5MCk0bQcTf/LVqZStvQ6K4lPn/BRg== 272 | dependencies: 273 | "@typescript-eslint/types" "8.24.1" 274 | "@typescript-eslint/visitor-keys" "8.24.1" 275 | debug "^4.3.4" 276 | fast-glob "^3.3.2" 277 | is-glob "^4.0.3" 278 | minimatch "^9.0.4" 279 | semver "^7.6.0" 280 | ts-api-utils "^2.0.1" 281 | 282 | "@typescript-eslint/utils@8.24.1": 283 | version "8.24.1" 284 | resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.24.1.tgz#08d14eac33cfb3456feeee5a275b8ad3349e52ed" 285 | integrity sha512-OOcg3PMMQx9EXspId5iktsI3eMaXVwlhC8BvNnX6B5w9a4dVgpkQZuU8Hy67TolKcl+iFWq0XX+jbDGN4xWxjQ== 286 | dependencies: 287 | "@eslint-community/eslint-utils" "^4.4.0" 288 | "@typescript-eslint/scope-manager" "8.24.1" 289 | "@typescript-eslint/types" "8.24.1" 290 | "@typescript-eslint/typescript-estree" "8.24.1" 291 | 292 | "@typescript-eslint/visitor-keys@8.24.1": 293 | version "8.24.1" 294 | resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.24.1.tgz#8bdfe47a89195344b34eb21ef61251562148202b" 295 | integrity sha512-EwVHlp5l+2vp8CoqJm9KikPZgi3gbdZAtabKT9KPShGeOcJhsv4Zdo3oc8T8I0uKEmYoU4ItyxbptjF08enaxg== 296 | dependencies: 297 | "@typescript-eslint/types" "8.24.1" 298 | eslint-visitor-keys "^4.2.0" 299 | 300 | acorn-jsx@^5.3.2: 301 | version "5.3.2" 302 | resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" 303 | integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== 304 | 305 | acorn-walk@^8.1.1: 306 | version "8.3.4" 307 | resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" 308 | integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== 309 | dependencies: 310 | acorn "^8.11.0" 311 | 312 | acorn@^8.11.0, acorn@^8.14.0, acorn@^8.4.1: 313 | version "8.14.0" 314 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" 315 | integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== 316 | 317 | ajv@^6.12.4: 318 | version "6.12.6" 319 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" 320 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 321 | dependencies: 322 | fast-deep-equal "^3.1.1" 323 | fast-json-stable-stringify "^2.0.0" 324 | json-schema-traverse "^0.4.1" 325 | uri-js "^4.2.2" 326 | 327 | ansi-regex@^5.0.1: 328 | version "5.0.1" 329 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 330 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 331 | 332 | ansi-regex@^6.0.1: 333 | version "6.1.0" 334 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" 335 | integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== 336 | 337 | ansi-styles@^4.0.0, ansi-styles@^4.1.0: 338 | version "4.3.0" 339 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 340 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 341 | dependencies: 342 | color-convert "^2.0.1" 343 | 344 | ansi-styles@^6.1.0: 345 | version "6.2.1" 346 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" 347 | integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== 348 | 349 | arg@^4.1.0: 350 | version "4.1.3" 351 | resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" 352 | integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== 353 | 354 | argparse@^2.0.1: 355 | version "2.0.1" 356 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" 357 | integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== 358 | 359 | balanced-match@^1.0.0: 360 | version "1.0.2" 361 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 362 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 363 | 364 | brace-expansion@^1.1.7: 365 | version "1.1.11" 366 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 367 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 368 | dependencies: 369 | balanced-match "^1.0.0" 370 | concat-map "0.0.1" 371 | 372 | brace-expansion@^2.0.1: 373 | version "2.0.1" 374 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" 375 | integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== 376 | dependencies: 377 | balanced-match "^1.0.0" 378 | 379 | braces@^3.0.3: 380 | version "3.0.3" 381 | resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" 382 | integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== 383 | dependencies: 384 | fill-range "^7.1.1" 385 | 386 | bytes@3.1.2: 387 | version "3.1.2" 388 | resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" 389 | integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== 390 | 391 | callsites@^3.0.0: 392 | version "3.1.0" 393 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" 394 | integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 395 | 396 | chalk@^4.0.0: 397 | version "4.1.2" 398 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 399 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 400 | dependencies: 401 | ansi-styles "^4.1.0" 402 | supports-color "^7.1.0" 403 | 404 | color-convert@^2.0.1: 405 | version "2.0.1" 406 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 407 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 408 | dependencies: 409 | color-name "~1.1.4" 410 | 411 | color-name@~1.1.4: 412 | version "1.1.4" 413 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 414 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 415 | 416 | commander@^13.1.0: 417 | version "13.1.0" 418 | resolved "https://registry.yarnpkg.com/commander/-/commander-13.1.0.tgz#776167db68c78f38dcce1f9b8d7b8b9a488abf46" 419 | integrity sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw== 420 | 421 | concat-map@0.0.1: 422 | version "0.0.1" 423 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 424 | integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== 425 | 426 | content-type@^1.0.5: 427 | version "1.0.5" 428 | resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" 429 | integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== 430 | 431 | create-require@^1.1.0: 432 | version "1.1.1" 433 | resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" 434 | integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== 435 | 436 | cross-spawn@^7.0.6: 437 | version "7.0.6" 438 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" 439 | integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== 440 | dependencies: 441 | path-key "^3.1.0" 442 | shebang-command "^2.0.0" 443 | which "^2.0.1" 444 | 445 | debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: 446 | version "4.4.0" 447 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" 448 | integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== 449 | dependencies: 450 | ms "^2.1.3" 451 | 452 | deep-is@^0.1.3: 453 | version "0.1.4" 454 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" 455 | integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== 456 | 457 | depd@2.0.0: 458 | version "2.0.0" 459 | resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" 460 | integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== 461 | 462 | diff@^4.0.1: 463 | version "4.0.2" 464 | resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" 465 | integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== 466 | 467 | eastasianwidth@^0.2.0: 468 | version "0.2.0" 469 | resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" 470 | integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== 471 | 472 | emoji-regex@^8.0.0: 473 | version "8.0.0" 474 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 475 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 476 | 477 | emoji-regex@^9.2.2: 478 | version "9.2.2" 479 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" 480 | integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== 481 | 482 | escape-string-regexp@^4.0.0: 483 | version "4.0.0" 484 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" 485 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 486 | 487 | eslint-config-prettier@^10.0.1: 488 | version "10.0.1" 489 | resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-10.0.1.tgz#fbb03bfc8db0651df9ce4e8b7150d11c5fe3addf" 490 | integrity sha512-lZBts941cyJyeaooiKxAtzoPHTN+GbQTJFAIdQbRhA4/8whaAraEh47Whw/ZFfrjNSnlAxqfm9i0XVAEkULjCw== 491 | 492 | eslint-plugin-prettier@^5.2.3: 493 | version "5.2.3" 494 | resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz#c4af01691a6fa9905207f0fbba0d7bea0902cce5" 495 | integrity sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw== 496 | dependencies: 497 | prettier-linter-helpers "^1.0.0" 498 | synckit "^0.9.1" 499 | 500 | eslint-scope@^8.2.0: 501 | version "8.2.0" 502 | resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.2.0.tgz#377aa6f1cb5dc7592cfd0b7f892fd0cf352ce442" 503 | integrity sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A== 504 | dependencies: 505 | esrecurse "^4.3.0" 506 | estraverse "^5.2.0" 507 | 508 | eslint-visitor-keys@^3.4.3: 509 | version "3.4.3" 510 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" 511 | integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== 512 | 513 | eslint-visitor-keys@^4.2.0: 514 | version "4.2.0" 515 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz#687bacb2af884fcdda8a6e7d65c606f46a14cd45" 516 | integrity sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw== 517 | 518 | eslint@^9.21.0: 519 | version "9.21.0" 520 | resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.21.0.tgz#b1c9c16f5153ff219791f627b94ab8f11f811591" 521 | integrity sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg== 522 | dependencies: 523 | "@eslint-community/eslint-utils" "^4.2.0" 524 | "@eslint-community/regexpp" "^4.12.1" 525 | "@eslint/config-array" "^0.19.2" 526 | "@eslint/core" "^0.12.0" 527 | "@eslint/eslintrc" "^3.3.0" 528 | "@eslint/js" "9.21.0" 529 | "@eslint/plugin-kit" "^0.2.7" 530 | "@humanfs/node" "^0.16.6" 531 | "@humanwhocodes/module-importer" "^1.0.1" 532 | "@humanwhocodes/retry" "^0.4.2" 533 | "@types/estree" "^1.0.6" 534 | "@types/json-schema" "^7.0.15" 535 | ajv "^6.12.4" 536 | chalk "^4.0.0" 537 | cross-spawn "^7.0.6" 538 | debug "^4.3.2" 539 | escape-string-regexp "^4.0.0" 540 | eslint-scope "^8.2.0" 541 | eslint-visitor-keys "^4.2.0" 542 | espree "^10.3.0" 543 | esquery "^1.5.0" 544 | esutils "^2.0.2" 545 | fast-deep-equal "^3.1.3" 546 | file-entry-cache "^8.0.0" 547 | find-up "^5.0.0" 548 | glob-parent "^6.0.2" 549 | ignore "^5.2.0" 550 | imurmurhash "^0.1.4" 551 | is-glob "^4.0.0" 552 | json-stable-stringify-without-jsonify "^1.0.1" 553 | lodash.merge "^4.6.2" 554 | minimatch "^3.1.2" 555 | natural-compare "^1.4.0" 556 | optionator "^0.9.3" 557 | 558 | espree@^10.0.1, espree@^10.3.0: 559 | version "10.3.0" 560 | resolved "https://registry.yarnpkg.com/espree/-/espree-10.3.0.tgz#29267cf5b0cb98735b65e64ba07e0ed49d1eed8a" 561 | integrity sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg== 562 | dependencies: 563 | acorn "^8.14.0" 564 | acorn-jsx "^5.3.2" 565 | eslint-visitor-keys "^4.2.0" 566 | 567 | esquery@^1.5.0: 568 | version "1.6.0" 569 | resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" 570 | integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== 571 | dependencies: 572 | estraverse "^5.1.0" 573 | 574 | esrecurse@^4.3.0: 575 | version "4.3.0" 576 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" 577 | integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== 578 | dependencies: 579 | estraverse "^5.2.0" 580 | 581 | estraverse@^5.1.0, estraverse@^5.2.0: 582 | version "5.3.0" 583 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" 584 | integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== 585 | 586 | esutils@^2.0.2: 587 | version "2.0.3" 588 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" 589 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 590 | 591 | eventsource-parser@^3.0.0: 592 | version "3.0.0" 593 | resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-3.0.0.tgz#9303e303ef807d279ee210a17ce80f16300d9f57" 594 | integrity sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA== 595 | 596 | eventsource@^3.0.2: 597 | version "3.0.5" 598 | resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-3.0.5.tgz#0cae1eee2d2c75894de8b02a91d84e5c57f0cc5a" 599 | integrity sha512-LT/5J605bx5SNyE+ITBDiM3FxffBiq9un7Vx0EwMDM3vg8sWKx/tO2zC+LMqZ+smAM0F2hblaDZUVZF0te2pSw== 600 | dependencies: 601 | eventsource-parser "^3.0.0" 602 | 603 | fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: 604 | version "3.1.3" 605 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 606 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 607 | 608 | fast-diff@^1.1.2: 609 | version "1.3.0" 610 | resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" 611 | integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== 612 | 613 | fast-glob@^3.3.2: 614 | version "3.3.3" 615 | resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" 616 | integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== 617 | dependencies: 618 | "@nodelib/fs.stat" "^2.0.2" 619 | "@nodelib/fs.walk" "^1.2.3" 620 | glob-parent "^5.1.2" 621 | merge2 "^1.3.0" 622 | micromatch "^4.0.8" 623 | 624 | fast-json-stable-stringify@^2.0.0: 625 | version "2.1.0" 626 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 627 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 628 | 629 | fast-levenshtein@^2.0.6: 630 | version "2.0.6" 631 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" 632 | integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== 633 | 634 | fastq@^1.6.0: 635 | version "1.19.0" 636 | resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.0.tgz#a82c6b7c2bb4e44766d865f07997785fecfdcb89" 637 | integrity sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA== 638 | dependencies: 639 | reusify "^1.0.4" 640 | 641 | file-entry-cache@^8.0.0: 642 | version "8.0.0" 643 | resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" 644 | integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== 645 | dependencies: 646 | flat-cache "^4.0.0" 647 | 648 | fill-range@^7.1.1: 649 | version "7.1.1" 650 | resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" 651 | integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== 652 | dependencies: 653 | to-regex-range "^5.0.1" 654 | 655 | find-up@^5.0.0: 656 | version "5.0.0" 657 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" 658 | integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== 659 | dependencies: 660 | locate-path "^6.0.0" 661 | path-exists "^4.0.0" 662 | 663 | flat-cache@^4.0.0: 664 | version "4.0.1" 665 | resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" 666 | integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== 667 | dependencies: 668 | flatted "^3.2.9" 669 | keyv "^4.5.4" 670 | 671 | flatted@^3.2.9: 672 | version "3.3.3" 673 | resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" 674 | integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== 675 | 676 | foreground-child@^3.1.0: 677 | version "3.3.1" 678 | resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" 679 | integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== 680 | dependencies: 681 | cross-spawn "^7.0.6" 682 | signal-exit "^4.0.1" 683 | 684 | glob-parent@^5.1.2: 685 | version "5.1.2" 686 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" 687 | integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== 688 | dependencies: 689 | is-glob "^4.0.1" 690 | 691 | glob-parent@^6.0.2: 692 | version "6.0.2" 693 | resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" 694 | integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== 695 | dependencies: 696 | is-glob "^4.0.3" 697 | 698 | glob@^11.0.0: 699 | version "11.0.1" 700 | resolved "https://registry.yarnpkg.com/glob/-/glob-11.0.1.tgz#1c3aef9a59d680e611b53dcd24bb8639cef064d9" 701 | integrity sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw== 702 | dependencies: 703 | foreground-child "^3.1.0" 704 | jackspeak "^4.0.1" 705 | minimatch "^10.0.0" 706 | minipass "^7.1.2" 707 | package-json-from-dist "^1.0.0" 708 | path-scurry "^2.0.0" 709 | 710 | globals@^14.0.0: 711 | version "14.0.0" 712 | resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" 713 | integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== 714 | 715 | graphemer@^1.4.0: 716 | version "1.4.0" 717 | resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" 718 | integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== 719 | 720 | has-flag@^4.0.0: 721 | version "4.0.0" 722 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 723 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 724 | 725 | http-errors@2.0.0: 726 | version "2.0.0" 727 | resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" 728 | integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== 729 | dependencies: 730 | depd "2.0.0" 731 | inherits "2.0.4" 732 | setprototypeof "1.2.0" 733 | statuses "2.0.1" 734 | toidentifier "1.0.1" 735 | 736 | iconv-lite@0.6.3: 737 | version "0.6.3" 738 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" 739 | integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== 740 | dependencies: 741 | safer-buffer ">= 2.1.2 < 3.0.0" 742 | 743 | ignore@^5.2.0, ignore@^5.3.1: 744 | version "5.3.2" 745 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" 746 | integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== 747 | 748 | import-fresh@^3.2.1: 749 | version "3.3.1" 750 | resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" 751 | integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== 752 | dependencies: 753 | parent-module "^1.0.0" 754 | resolve-from "^4.0.0" 755 | 756 | imurmurhash@^0.1.4: 757 | version "0.1.4" 758 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 759 | integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== 760 | 761 | inherits@2.0.4: 762 | version "2.0.4" 763 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 764 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 765 | 766 | is-extglob@^2.1.1: 767 | version "2.1.1" 768 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 769 | integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== 770 | 771 | is-fullwidth-code-point@^3.0.0: 772 | version "3.0.0" 773 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 774 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 775 | 776 | is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: 777 | version "4.0.3" 778 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" 779 | integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== 780 | dependencies: 781 | is-extglob "^2.1.1" 782 | 783 | is-number@^7.0.0: 784 | version "7.0.0" 785 | resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" 786 | integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== 787 | 788 | isexe@^2.0.0: 789 | version "2.0.0" 790 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 791 | integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== 792 | 793 | jackspeak@^4.0.1: 794 | version "4.1.0" 795 | resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.1.0.tgz#c489c079f2b636dc4cbe9b0312a13ff1282e561b" 796 | integrity sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw== 797 | dependencies: 798 | "@isaacs/cliui" "^8.0.2" 799 | 800 | js-yaml@^4.1.0: 801 | version "4.1.0" 802 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" 803 | integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== 804 | dependencies: 805 | argparse "^2.0.1" 806 | 807 | json-buffer@3.0.1: 808 | version "3.0.1" 809 | resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" 810 | integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== 811 | 812 | json-schema-traverse@^0.4.1: 813 | version "0.4.1" 814 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 815 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 816 | 817 | json-stable-stringify-without-jsonify@^1.0.1: 818 | version "1.0.1" 819 | resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" 820 | integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== 821 | 822 | keyv@^4.5.4: 823 | version "4.5.4" 824 | resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" 825 | integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== 826 | dependencies: 827 | json-buffer "3.0.1" 828 | 829 | levn@^0.4.1: 830 | version "0.4.1" 831 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" 832 | integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== 833 | dependencies: 834 | prelude-ls "^1.2.1" 835 | type-check "~0.4.0" 836 | 837 | locate-path@^6.0.0: 838 | version "6.0.0" 839 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" 840 | integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== 841 | dependencies: 842 | p-locate "^5.0.0" 843 | 844 | lodash.merge@^4.6.2: 845 | version "4.6.2" 846 | resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" 847 | integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== 848 | 849 | lru-cache@^11.0.0: 850 | version "11.0.2" 851 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.0.2.tgz#fbd8e7cf8211f5e7e5d91905c415a3f55755ca39" 852 | integrity sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA== 853 | 854 | make-error@^1.1.1: 855 | version "1.3.6" 856 | resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" 857 | integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== 858 | 859 | merge2@^1.3.0: 860 | version "1.4.1" 861 | resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" 862 | integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== 863 | 864 | micromatch@^4.0.8: 865 | version "4.0.8" 866 | resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" 867 | integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== 868 | dependencies: 869 | braces "^3.0.3" 870 | picomatch "^2.3.1" 871 | 872 | minimatch@^10.0.0: 873 | version "10.0.1" 874 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.1.tgz#ce0521856b453c86e25f2c4c0d03e6ff7ddc440b" 875 | integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ== 876 | dependencies: 877 | brace-expansion "^2.0.1" 878 | 879 | minimatch@^3.1.2: 880 | version "3.1.2" 881 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" 882 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 883 | dependencies: 884 | brace-expansion "^1.1.7" 885 | 886 | minimatch@^9.0.4: 887 | version "9.0.5" 888 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" 889 | integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== 890 | dependencies: 891 | brace-expansion "^2.0.1" 892 | 893 | minipass@^7.1.2: 894 | version "7.1.2" 895 | resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" 896 | integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== 897 | 898 | ms@^2.1.3: 899 | version "2.1.3" 900 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 901 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 902 | 903 | natural-compare@^1.4.0: 904 | version "1.4.0" 905 | resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" 906 | integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== 907 | 908 | optionator@^0.9.3: 909 | version "0.9.4" 910 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" 911 | integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== 912 | dependencies: 913 | deep-is "^0.1.3" 914 | fast-levenshtein "^2.0.6" 915 | levn "^0.4.1" 916 | prelude-ls "^1.2.1" 917 | type-check "^0.4.0" 918 | word-wrap "^1.2.5" 919 | 920 | p-limit@^3.0.2: 921 | version "3.1.0" 922 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" 923 | integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== 924 | dependencies: 925 | yocto-queue "^0.1.0" 926 | 927 | p-locate@^5.0.0: 928 | version "5.0.0" 929 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" 930 | integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== 931 | dependencies: 932 | p-limit "^3.0.2" 933 | 934 | package-json-from-dist@^1.0.0: 935 | version "1.0.1" 936 | resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" 937 | integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== 938 | 939 | parent-module@^1.0.0: 940 | version "1.0.1" 941 | resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" 942 | integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== 943 | dependencies: 944 | callsites "^3.0.0" 945 | 946 | path-exists@^4.0.0: 947 | version "4.0.0" 948 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 949 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 950 | 951 | path-key@^3.1.0: 952 | version "3.1.1" 953 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 954 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 955 | 956 | path-scurry@^2.0.0: 957 | version "2.0.0" 958 | resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-2.0.0.tgz#9f052289f23ad8bf9397a2a0425e7b8615c58580" 959 | integrity sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg== 960 | dependencies: 961 | lru-cache "^11.0.0" 962 | minipass "^7.1.2" 963 | 964 | picomatch@^2.3.1: 965 | version "2.3.1" 966 | resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" 967 | integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== 968 | 969 | prelude-ls@^1.2.1: 970 | version "1.2.1" 971 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" 972 | integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== 973 | 974 | prettier-linter-helpers@^1.0.0: 975 | version "1.0.0" 976 | resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" 977 | integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== 978 | dependencies: 979 | fast-diff "^1.1.2" 980 | 981 | prettier@^3.5.2: 982 | version "3.5.2" 983 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.5.2.tgz#d066c6053200da0234bf8fa1ef45168abed8b914" 984 | integrity sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg== 985 | 986 | punycode@^2.1.0: 987 | version "2.3.1" 988 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" 989 | integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== 990 | 991 | queue-microtask@^1.2.2: 992 | version "1.2.3" 993 | resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" 994 | integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== 995 | 996 | raw-body@^3.0.0: 997 | version "3.0.0" 998 | resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-3.0.0.tgz#25b3476f07a51600619dae3fe82ddc28a36e5e0f" 999 | integrity sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g== 1000 | dependencies: 1001 | bytes "3.1.2" 1002 | http-errors "2.0.0" 1003 | iconv-lite "0.6.3" 1004 | unpipe "1.0.0" 1005 | 1006 | resolve-from@^4.0.0: 1007 | version "4.0.0" 1008 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" 1009 | integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 1010 | 1011 | reusify@^1.0.4: 1012 | version "1.0.4" 1013 | resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" 1014 | integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== 1015 | 1016 | rimraf@^6.0.1: 1017 | version "6.0.1" 1018 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-6.0.1.tgz#ffb8ad8844dd60332ab15f52bc104bc3ed71ea4e" 1019 | integrity sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A== 1020 | dependencies: 1021 | glob "^11.0.0" 1022 | package-json-from-dist "^1.0.0" 1023 | 1024 | run-parallel@^1.1.9: 1025 | version "1.2.0" 1026 | resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" 1027 | integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== 1028 | dependencies: 1029 | queue-microtask "^1.2.2" 1030 | 1031 | "safer-buffer@>= 2.1.2 < 3.0.0": 1032 | version "2.1.2" 1033 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 1034 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 1035 | 1036 | semver@^7.6.0: 1037 | version "7.7.1" 1038 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" 1039 | integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== 1040 | 1041 | setprototypeof@1.2.0: 1042 | version "1.2.0" 1043 | resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" 1044 | integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== 1045 | 1046 | shebang-command@^2.0.0: 1047 | version "2.0.0" 1048 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" 1049 | integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== 1050 | dependencies: 1051 | shebang-regex "^3.0.0" 1052 | 1053 | shebang-regex@^3.0.0: 1054 | version "3.0.0" 1055 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" 1056 | integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== 1057 | 1058 | signal-exit@^4.0.1: 1059 | version "4.1.0" 1060 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" 1061 | integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== 1062 | 1063 | statuses@2.0.1: 1064 | version "2.0.1" 1065 | resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" 1066 | integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== 1067 | 1068 | "string-width-cjs@npm:string-width@^4.2.0": 1069 | version "4.2.3" 1070 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 1071 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 1072 | dependencies: 1073 | emoji-regex "^8.0.0" 1074 | is-fullwidth-code-point "^3.0.0" 1075 | strip-ansi "^6.0.1" 1076 | 1077 | string-width@^4.1.0: 1078 | version "4.2.3" 1079 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 1080 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 1081 | dependencies: 1082 | emoji-regex "^8.0.0" 1083 | is-fullwidth-code-point "^3.0.0" 1084 | strip-ansi "^6.0.1" 1085 | 1086 | string-width@^5.0.1, string-width@^5.1.2: 1087 | version "5.1.2" 1088 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" 1089 | integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== 1090 | dependencies: 1091 | eastasianwidth "^0.2.0" 1092 | emoji-regex "^9.2.2" 1093 | strip-ansi "^7.0.1" 1094 | 1095 | "strip-ansi-cjs@npm:strip-ansi@^6.0.1": 1096 | version "6.0.1" 1097 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 1098 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 1099 | dependencies: 1100 | ansi-regex "^5.0.1" 1101 | 1102 | strip-ansi@^6.0.0, strip-ansi@^6.0.1: 1103 | version "6.0.1" 1104 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 1105 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 1106 | dependencies: 1107 | ansi-regex "^5.0.1" 1108 | 1109 | strip-ansi@^7.0.1: 1110 | version "7.1.0" 1111 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" 1112 | integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== 1113 | dependencies: 1114 | ansi-regex "^6.0.1" 1115 | 1116 | strip-json-comments@^3.1.1: 1117 | version "3.1.1" 1118 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" 1119 | integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 1120 | 1121 | strip-json-comments@^5.0.1: 1122 | version "5.0.1" 1123 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-5.0.1.tgz#0d8b7d01b23848ed7dbdf4baaaa31a8250d8cfa0" 1124 | integrity sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw== 1125 | 1126 | supports-color@^7.1.0: 1127 | version "7.2.0" 1128 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 1129 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 1130 | dependencies: 1131 | has-flag "^4.0.0" 1132 | 1133 | synckit@^0.9.1: 1134 | version "0.9.2" 1135 | resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.9.2.tgz#a3a935eca7922d48b9e7d6c61822ee6c3ae4ec62" 1136 | integrity sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw== 1137 | dependencies: 1138 | "@pkgr/core" "^0.1.0" 1139 | tslib "^2.6.2" 1140 | 1141 | to-regex-range@^5.0.1: 1142 | version "5.0.1" 1143 | resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" 1144 | integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== 1145 | dependencies: 1146 | is-number "^7.0.0" 1147 | 1148 | toidentifier@1.0.1: 1149 | version "1.0.1" 1150 | resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" 1151 | integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== 1152 | 1153 | ts-api-utils@^2.0.1: 1154 | version "2.0.1" 1155 | resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.0.1.tgz#660729385b625b939aaa58054f45c058f33f10cd" 1156 | integrity sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w== 1157 | 1158 | ts-node@^10.9.2: 1159 | version "10.9.2" 1160 | resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" 1161 | integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== 1162 | dependencies: 1163 | "@cspotcode/source-map-support" "^0.8.0" 1164 | "@tsconfig/node10" "^1.0.7" 1165 | "@tsconfig/node12" "^1.0.7" 1166 | "@tsconfig/node14" "^1.0.0" 1167 | "@tsconfig/node16" "^1.0.2" 1168 | acorn "^8.4.1" 1169 | acorn-walk "^8.1.1" 1170 | arg "^4.1.0" 1171 | create-require "^1.1.0" 1172 | diff "^4.0.1" 1173 | make-error "^1.1.1" 1174 | v8-compile-cache-lib "^3.0.1" 1175 | yn "3.1.1" 1176 | 1177 | tslib@^2.6.2: 1178 | version "2.8.1" 1179 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" 1180 | integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== 1181 | 1182 | type-check@^0.4.0, type-check@~0.4.0: 1183 | version "0.4.0" 1184 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" 1185 | integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== 1186 | dependencies: 1187 | prelude-ls "^1.2.1" 1188 | 1189 | typescript-language-server@^4.3.3: 1190 | version "4.3.3" 1191 | resolved "https://registry.yarnpkg.com/typescript-language-server/-/typescript-language-server-4.3.3.tgz#b52836fa0ec7a9c05007af44d5a49605f5fe72e0" 1192 | integrity sha512-3QLj57Ru9S6zv10sa4z1pA3TIR1Rdkd04Ke0EszbO4fx5PLdlYhlC/PMxwlyxls9wrZs7wPCME1Ru0s1Gabz4Q== 1193 | 1194 | typescript@^5.7.3: 1195 | version "5.7.3" 1196 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.3.tgz#919b44a7dbb8583a9b856d162be24a54bf80073e" 1197 | integrity sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw== 1198 | 1199 | undici-types@~6.20.0: 1200 | version "6.20.0" 1201 | resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" 1202 | integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== 1203 | 1204 | unpipe@1.0.0: 1205 | version "1.0.0" 1206 | resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" 1207 | integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== 1208 | 1209 | uri-js@^4.2.2: 1210 | version "4.4.1" 1211 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" 1212 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 1213 | dependencies: 1214 | punycode "^2.1.0" 1215 | 1216 | v8-compile-cache-lib@^3.0.1: 1217 | version "3.0.1" 1218 | resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" 1219 | integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== 1220 | 1221 | vscode-jsonrpc@8.2.0: 1222 | version "8.2.0" 1223 | resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz#f43dfa35fb51e763d17cd94dcca0c9458f35abf9" 1224 | integrity sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA== 1225 | 1226 | vscode-languageserver-protocol@^3.17.5: 1227 | version "3.17.5" 1228 | resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz#864a8b8f390835572f4e13bd9f8313d0e3ac4bea" 1229 | integrity sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg== 1230 | dependencies: 1231 | vscode-jsonrpc "8.2.0" 1232 | vscode-languageserver-types "3.17.5" 1233 | 1234 | vscode-languageserver-types@3.17.5: 1235 | version "3.17.5" 1236 | resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz#3273676f0cf2eab40b3f44d085acbb7f08a39d8a" 1237 | integrity sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg== 1238 | 1239 | which@^2.0.1: 1240 | version "2.0.2" 1241 | resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" 1242 | integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== 1243 | dependencies: 1244 | isexe "^2.0.0" 1245 | 1246 | word-wrap@^1.2.5: 1247 | version "1.2.5" 1248 | resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" 1249 | integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== 1250 | 1251 | "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": 1252 | version "7.0.0" 1253 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 1254 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== 1255 | dependencies: 1256 | ansi-styles "^4.0.0" 1257 | string-width "^4.1.0" 1258 | strip-ansi "^6.0.0" 1259 | 1260 | wrap-ansi@^8.1.0: 1261 | version "8.1.0" 1262 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" 1263 | integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== 1264 | dependencies: 1265 | ansi-styles "^6.1.0" 1266 | string-width "^5.0.1" 1267 | strip-ansi "^7.0.1" 1268 | 1269 | yn@3.1.1: 1270 | version "3.1.1" 1271 | resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" 1272 | integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== 1273 | 1274 | yocto-queue@^0.1.0: 1275 | version "0.1.0" 1276 | resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" 1277 | integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== 1278 | 1279 | zod-to-json-schema@^3.24.1: 1280 | version "3.24.3" 1281 | resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.3.tgz#5958ba111d681f8d01c5b6b647425c9b8a6059e7" 1282 | integrity sha512-HIAfWdYIt1sssHfYZFCXp4rU1w2r8hVVXYIlmoa0r0gABLs5di3RCqPU5DDROogVz1pAdYBaz7HK5n9pSUNs3A== 1283 | 1284 | zod@^3.23.8, zod@^3.24.2: 1285 | version "3.24.2" 1286 | resolved "https://registry.yarnpkg.com/zod/-/zod-3.24.2.tgz#8efa74126287c675e92f46871cfc8d15c34372b3" 1287 | integrity sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ== 1288 | --------------------------------------------------------------------------------