├── .github └── workflows │ └── docker-publish.yaml ├── .gitignore ├── .husky └── pre-commit ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── docker-bake.hcl ├── docker ├── base.Dockerfile ├── deno.Dockerfile └── uvx.Dockerfile ├── package-lock.json ├── package.json ├── src ├── gateways │ ├── sseToStdio.ts │ ├── stdioToSse.ts │ ├── stdioToWs.ts │ └── streamableHttpToStdio.ts ├── index.ts ├── lib │ ├── corsOrigin.ts │ ├── getLogger.ts │ ├── getVersion.ts │ ├── headers.ts │ ├── onSignals.ts │ └── serializeCorsOrigin.ts ├── server │ └── websocket.ts └── types.ts ├── supergateway.png ├── tests ├── baseUrl.test.ts ├── concurrency.test.ts ├── protocolVersion.test.ts └── streamableHttpToStdio.test.ts ├── tsconfig.build.json └── tsconfig.json /.github/workflows/docker-publish.yaml: -------------------------------------------------------------------------------- 1 | name: Publish Docker images 2 | 3 | on: 4 | workflow_dispatch: {} 5 | push: 6 | tags: 7 | - "v*.*.*" 8 | 9 | permissions: 10 | contents: read 11 | 12 | env: 13 | GHCR_REGISTRY: ghcr.io/supercorp-ai 14 | DOCKERHUB_REGISTRY: docker.io/supercorp 15 | 16 | jobs: 17 | publish: 18 | name: Build and push supergateway container 19 | runs-on: ubuntu-latest 20 | permissions: 21 | contents: read 22 | id-token: write 23 | packages: write 24 | steps: 25 | - name: Checkout 26 | uses: actions/checkout@v4 27 | with: 28 | fetch-depth: 0 29 | 30 | - name: Set up QEMU 31 | uses: docker/setup-qemu-action@v3 32 | 33 | - name: Set up Docker Buildx 34 | uses: docker/setup-buildx-action@v3 35 | 36 | - name: Login to GHCR 37 | uses: docker/login-action@v3 38 | with: 39 | registry: ghcr.io 40 | username: ${{ github.repository_owner }} 41 | password: ${{ secrets.GITHUB_TOKEN }} 42 | 43 | - name: Login to Docker Hub 44 | uses: docker/login-action@v3 45 | with: 46 | registry: docker.io 47 | username: ${{ secrets.DOCKERHUB_USERNAME }} 48 | password: ${{ secrets.DOCKERHUB_TOKEN }} 49 | 50 | - name: Extract version 51 | id: ver 52 | run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> "$GITHUB_OUTPUT" 53 | 54 | - name: Docker meta 55 | id: docker_meta 56 | uses: docker/metadata-action@v5 57 | with: 58 | images: | 59 | ${{ env.GHCR_REGISTRY }}/supergateway 60 | ${{ env.DOCKERHUB_REGISTRY }}/supergateway 61 | labels: | 62 | org.opencontainers.image.title=Supergateway 63 | org.opencontainers.image.version=${{ steps.ver.outputs.VERSION }} 64 | org.opencontainers.image.source=${{ github.repository }} 65 | 66 | - name: Build & push (Bake) 67 | uses: docker/bake-action@v6 68 | env: 69 | VERSION: ${{ steps.ver.outputs.VERSION }} 70 | with: 71 | source: . 72 | files: | 73 | docker-bake.hcl 74 | ${{ steps.docker_meta.outputs.bake-file }} 75 | push: true 76 | set: | 77 | *.args.VERSION=${{ steps.ver.outputs.VERSION }} 78 | *.cache-from=type=gha 79 | *.cache-to=type=gha,mode=max 80 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | # Ensure we're in the project directory 5 | GIT_ROOT=$(git rev-parse --show-toplevel) 6 | cd "$GIT_ROOT" || exit 1 7 | 8 | # Get staged files 9 | STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(js|jsx|ts|tsx|json|css|scss|md|yaml|yml)$' || true) 10 | 11 | if [ -n "$STAGED_FILES" ]; then 12 | echo "Formatting staged files before commit..." 13 | # Use the installed Prettier to format only the staged files 14 | ./node_modules/.bin/prettier --write --ignore-unknown $STAGED_FILES 15 | # Re-add the formatted files to the staging area 16 | git add $STAGED_FILES 17 | fi -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | .git 4 | .github 5 | package-lock.json 6 | .DS_Store 7 | **/.hermit/** 8 | **/cache/** 9 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "singleAttributePerLine": true 5 | } 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Supercorp 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Supergateway: Run stdio MCP servers over SSE and WS](https://raw.githubusercontent.com/supercorp-ai/supergateway/main/supergateway.png) 2 | 3 | **Supergateway** runs **MCP stdio-based servers** over **SSE (Server-Sent Events)** or **WebSockets (WS)** with one command. This is useful for remote access, debugging, or connecting to clients when your MCP server only supports stdio. 4 | 5 | Supported by [Supermachine](https://supermachine.ai) (hosted MCPs), [Superinterface](https://superinterface.ai), and [Supercorp](https://supercorp.ai). 6 | 7 | ## Installation & Usage 8 | 9 | Run Supergateway via `npx`: 10 | 11 | ```bash 12 | npx -y supergateway --stdio "uvx mcp-server-git" 13 | ``` 14 | 15 | - **`--stdio "command"`**: Command that runs an MCP server over stdio 16 | - **`--sse "https://mcp-server-ab71a6b2-cd55-49d0-adba-562bc85956e3.supermachine.app"`**: SSE URL to connect to (SSE→stdio mode) 17 | - **`--streamableHttp "https://mcp-server.example.com/mcp"`**: Streamable HTTP URL to connect to (StreamableHTTP→stdio mode) 18 | - **`--outputTransport stdio | sse | ws`**: Output MCP transport (default: `sse` with `--stdio`, `stdio` with `--sse`) 19 | - **`--port 8000`**: Port to listen on (stdio→SSE or stdio→WS mode, default: `8000`) 20 | - **`--baseUrl "http://localhost:8000"`**: Base URL for SSE or WS clients (stdio→SSE mode; optional) 21 | - **`--ssePath "/sse"`**: Path for SSE subscriptions (stdio→SSE mode, default: `/sse`) 22 | - **`--messagePath "/message"`**: Path for messages (stdio→SSE or stdio→WS mode, default: `/message`) 23 | - **`--header "x-user-id: 123"`**: Add one or more headers (stdio→SSE, SSE→stdio, or Streamable HTTP→stdio mode; can be used multiple times) 24 | - **`--oauth2Bearer "some-access-token"`**: Adds an `Authorization` header with the provided Bearer token 25 | - **`--logLevel debug | info | none`**: Controls logging level (default: `info`). Use `debug` for more verbose logs, `none` to suppress all logs. 26 | - **`--cors`**: Enable CORS (stdio→SSE or stdio→WS mode). Use `--cors` with no values to allow all origins, or supply one or more allowed origins (e.g. `--cors "http://example.com"` or `--cors "/example\\.com$/"` for regex matching). 27 | - **`--healthEndpoint /healthz`**: Register one or more endpoints (stdio→SSE or stdio→WS mode; can be used multiple times) that respond with `"ok"` 28 | 29 | ## stdio → SSE 30 | 31 | Expose an MCP stdio server as an SSE server: 32 | 33 | ```bash 34 | npx -y supergateway \ 35 | --stdio "npx -y @modelcontextprotocol/server-filesystem ./my-folder" \ 36 | --port 8000 --baseUrl http://localhost:8000 \ 37 | --ssePath /sse --messagePath /message 38 | ``` 39 | 40 | - **Subscribe to events**: `GET http://localhost:8000/sse` 41 | - **Send messages**: `POST http://localhost:8000/message` 42 | 43 | ## SSE → stdio 44 | 45 | Connect to a remote SSE server and expose locally via stdio: 46 | 47 | ```bash 48 | npx -y supergateway --sse "https://mcp-server-ab71a6b2-cd55-49d0-adba-562bc85956e3.supermachine.app" 49 | ``` 50 | 51 | Useful for integrating remote SSE MCP servers into local command-line environments. 52 | 53 | You can also pass headers when sending requests. This is useful for authentication: 54 | 55 | ```bash 56 | npx -y supergateway \ 57 | --sse "https://mcp-server-ab71a6b2-cd55-49d0-adba-562bc85956e3.supermachine.app" \ 58 | --oauth2Bearer "some-access-token" \ 59 | --header "X-My-Header: another-header-value" 60 | ``` 61 | 62 | ## Streamable HTTP → stdio 63 | 64 | Connect to a remote Streamable HTTP server and expose locally via stdio: 65 | 66 | ```bash 67 | npx -y supergateway --streamableHttp "https://mcp-server.example.com/mcp" 68 | ``` 69 | 70 | This mode is useful for connecting to MCP servers that use the newer Streamable HTTP transport protocol. Like SSE mode, you can also pass headers for authentication: 71 | 72 | ```bash 73 | npx -y supergateway \ 74 | --streamableHttp "https://mcp-server.example.com/mcp" \ 75 | --oauth2Bearer "some-access-token" \ 76 | --header "X-My-Header: another-header-value" 77 | ``` 78 | 79 | ## stdio → WS 80 | 81 | Expose an MCP stdio server as a WebSocket server: 82 | 83 | ```bash 84 | npx -y supergateway \ 85 | --stdio "npx -y @modelcontextprotocol/server-filesystem ./my-folder" \ 86 | --port 8000 --outputTransport ws --messagePath /message 87 | ``` 88 | 89 | - **WebSocket endpoint**: `ws://localhost:8000/message` 90 | 91 | ## Example with MCP Inspector (stdio → SSE mode) 92 | 93 | 1. **Run Supergateway**: 94 | 95 | ```bash 96 | npx -y supergateway --port 8000 \ 97 | --stdio "npx -y @modelcontextprotocol/server-filesystem /Users/MyName/Desktop" 98 | ``` 99 | 100 | 2. **Use MCP Inspector**: 101 | 102 | ```bash 103 | npx @modelcontextprotocol/inspector 104 | ``` 105 | 106 | You can now list tools, resources, or perform MCP actions via Supergateway. 107 | 108 | ## Using with ngrok 109 | 110 | Use [ngrok](https://ngrok.com/) to share your local MCP server publicly: 111 | 112 | ```bash 113 | npx -y supergateway --port 8000 --stdio "npx -y @modelcontextprotocol/server-filesystem ." 114 | 115 | # In another terminal: 116 | ngrok http 8000 117 | ``` 118 | 119 | ngrok provides a public URL for remote access. 120 | 121 | MCP server will be available at URL similar to: https://1234-567-890-12-456.ngrok-free.app/sse 122 | 123 | ## Running with Docker 124 | 125 | A Docker-based workflow avoids local Node.js setup. A ready-to-run Docker image is available here: 126 | [supercorp/supergateway](https://hub.docker.com/r/supercorp/supergateway). Also on GHCR: [ghcr.io/supercorp-ai/supergateway](https://github.com/supercorp-ai/supergateway/pkgs/container/supergateway) 127 | 128 | ### Using the Official Image 129 | 130 | ```bash 131 | docker run -it --rm -p 8000:8000 supercorp/supergateway \ 132 | --stdio "npx -y @modelcontextprotocol/server-filesystem /" \ 133 | --port 8000 134 | ``` 135 | 136 | Docker pulls the image automatically. The MCP server runs in the container’s root directory (`/`). You can mount host directories if needed. 137 | 138 | #### Images with dependencies 139 | 140 | Pull any of these pre-built Supergateway images for various dependencies you might need. 141 | 142 | - **uvx** 143 | Supergateway + uv/uvx, so you can call `uvx` directly: 144 | 145 | ```bash 146 | docker run -it --rm -p 8000:8000 supercorp/supergateway:uvx \ 147 | --stdio "uvx mcp-server-fetch" 148 | ``` 149 | 150 | - **deno** 151 | Supergateway + Deno, ready to run Deno-based MCP servers: 152 | ```bash 153 | docker run -it --rm -p 8000:8000 supercorp/supergateway:deno \ 154 | --stdio "deno run -A jsr:@omedia/mcp-server-drupal --drupal-url https://your-drupal-server.com" 155 | ``` 156 | 157 | ### Building the Image Yourself 158 | 159 | Use provided Dockerfile: 160 | 161 | ```bash 162 | docker build -f docker/base.Dockerfile -t supergateway . 163 | 164 | docker run -it --rm -p 8000:8000 supergateway --stdio "npx -y @modelcontextprotocol/server-filesystem ." 165 | ``` 166 | 167 | ## Using with Claude Desktop (SSE → stdio mode) 168 | 169 | Claude Desktop can use Supergateway’s SSE→stdio mode. 170 | 171 | ### NPX-based MCP Server Example 172 | 173 | ```json 174 | { 175 | "mcpServers": { 176 | "supermachineExampleNpx": { 177 | "command": "npx", 178 | "args": [ 179 | "-y", 180 | "supergateway", 181 | "--sse", 182 | "https://mcp-server-ab71a6b2-cd55-49d0-adba-562bc85956e3.supermachine.app" 183 | ] 184 | } 185 | } 186 | } 187 | ``` 188 | 189 | ### Docker-based MCP Server Example 190 | 191 | ```json 192 | { 193 | "mcpServers": { 194 | "supermachineExampleDocker": { 195 | "command": "docker", 196 | "args": [ 197 | "run", 198 | "-i", 199 | "--rm", 200 | "supercorp/supergateway", 201 | "--sse", 202 | "https://mcp-server-ab71a6b2-cd55-49d0-adba-562bc85956e3.supermachine.app" 203 | ] 204 | } 205 | } 206 | } 207 | ``` 208 | 209 | ## Using with Cursor (SSE → stdio mode) 210 | 211 | Cursor can also integrate with Supergateway in SSE→stdio mode. The configuration is similar to Claude Desktop. 212 | 213 | ### NPX-based MCP Server Example for Cursor 214 | 215 | ```json 216 | { 217 | "mcpServers": { 218 | "cursorExampleNpx": { 219 | "command": "npx", 220 | "args": [ 221 | "-y", 222 | "supergateway", 223 | "--sse", 224 | "https://mcp-server-ab71a6b2-cd55-49d0-adba-562bc85956e3.supermachine.app" 225 | ] 226 | } 227 | } 228 | } 229 | ``` 230 | 231 | ### Docker-based MCP Server Example for Cursor 232 | 233 | ```json 234 | { 235 | "mcpServers": { 236 | "cursorExampleDocker": { 237 | "command": "docker", 238 | "args": [ 239 | "run", 240 | "-i", 241 | "--rm", 242 | "supercorp/supergateway", 243 | "--sse", 244 | "https://mcp-server-ab71a6b2-cd55-49d0-adba-562bc85956e3.supermachine.app" 245 | ] 246 | } 247 | } 248 | } 249 | ``` 250 | 251 | **Note:** Although the setup supports sending headers via the `--header` flag, if you need to pass an Authorization header (which typically includes a space, e.g. `"Bearer 123"`), you must use the `--oauth2Bearer` flag due to a known Cursor bug with spaces in command-line arguments. 252 | 253 | ## Why MCP? 254 | 255 | [Model Context Protocol](https://spec.modelcontextprotocol.io/) standardizes AI tool interactions. Supergateway converts MCP stdio servers into SSE or WS services, simplifying integration and debugging with web-based or remote clients. 256 | 257 | ## Advanced Configuration 258 | 259 | Supergateway emphasizes modularity: 260 | 261 | - Automatically manages JSON-RPC versioning. 262 | - Retransmits package metadata where possible. 263 | - stdio→SSE or stdio→WS mode logs via standard output; SSE→stdio mode logs via stderr. 264 | 265 | ## Additional resources 266 | 267 | - [Superargs](https://github.com/supercorp-ai/superargs) - provide arguments to MCP servers during runtime. 268 | 269 | ## Contributors 270 | 271 | - [@griffinqiu](https://github.com/griffinqiu) 272 | - [@folkvir](https://github.com/folkvir) 273 | - [@wizizm](https://github.com/wizizm) 274 | - [@dtinth](https://github.com/dtinth) 275 | - [@rajivml](https://github.com/rajivml) 276 | - [@NicoBonaminio](https://github.com/NicoBonaminio) 277 | - [@sibbl](https://github.com/sibbl) 278 | - [@podarok](https://github.com/podarok) 279 | - [@jmn8718](https://github.com/jmn8718) 280 | - [@TraceIvan](https://github.com/TraceIvan) 281 | - [@zhoufei0622](https://github.com/zhoufei0622) 282 | - [@ezyang](https://github.com/ezyang) 283 | - [@aleksadvaisly](https://github.com/aleksadvaisly) 284 | - [@wuzhuoquan](https://github.com/wuzhuoquan) 285 | - [@mantrakp04](https://github.com/mantrakp04) 286 | - [@mheubi](https://github.com/mheubi) 287 | - [@mjmendo](https://github.com/mjmendo) 288 | - [@CyanMystery](https://github.com/CyanMystery) 289 | - [@earonesty](https://github.com/earonesty) 290 | - [@StefanBurscher](https://github.com/StefanBurscher) 291 | - [@tarasyarema](https://github.com/tarasyarema) 292 | - [@pcnfernando](https://github.com/pcnfernando) 293 | - [@Areo-Joe](https://github.com/Areo-Joe) 294 | - [@Joffref](https://github.com/Joffref) 295 | - [@michaeljguarino](https://github.com/michaeljguarino) 296 | 297 | ## Contributing 298 | 299 | Issues and PRs welcome. Please open one if you encounter problems or have feature suggestions. 300 | 301 | ## Tests 302 | 303 | Supergateway is tested with Node Test Runner. 304 | 305 | To run tests locally, Node version 24+ that supports [`--experimental-test-module-mocks`](https://nodejs.org/api/cli.html#--experimental-test-module-mocks) is required. 306 | 307 | Run tests with: 308 | 309 | ```bash 310 | npm test 311 | ``` 312 | 313 | ## License 314 | 315 | [MIT License](./LICENSE) 316 | -------------------------------------------------------------------------------- /docker-bake.hcl: -------------------------------------------------------------------------------- 1 | variable "VERSION" { 2 | default = "DEV" 3 | } 4 | 5 | target "common" { 6 | context = "." 7 | platforms = ["linux/amd64", "linux/arm64"] 8 | } 9 | 10 | group "default" { 11 | targets = ["base", "uvx", "deno"] 12 | } 13 | 14 | target "base" { 15 | inherits = ["common"] 16 | dockerfile = "docker/base.Dockerfile" 17 | tags = [ 18 | "supercorp/supergateway:latest", 19 | "supercorp/supergateway:base", 20 | "supercorp/supergateway:${VERSION}" 21 | ] 22 | } 23 | 24 | target "uvx" { 25 | inherits = ["common"] 26 | depends_on = ["base"] 27 | dockerfile = "docker/uvx.Dockerfile" 28 | contexts = { base = "target:base" } 29 | tags = [ 30 | "supercorp/supergateway:uvx", 31 | "supercorp/supergateway:${VERSION}-uvx" 32 | ] 33 | } 34 | 35 | target "deno" { 36 | inherits = ["common"] 37 | depends_on = ["base"] 38 | dockerfile = "docker/deno.Dockerfile" 39 | contexts = { base = "target:base" } 40 | tags = [ 41 | "supercorp/supergateway:deno", 42 | "supercorp/supergateway:${VERSION}-deno" 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /docker/base.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:20-alpine 2 | 3 | RUN npm install -g supergateway 4 | 5 | EXPOSE 8000 6 | 7 | ENTRYPOINT ["supergateway"] 8 | 9 | CMD ["--help"] 10 | -------------------------------------------------------------------------------- /docker/deno.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM base 2 | RUN curl -fsSL https://deno.land/install.sh | sh 3 | -------------------------------------------------------------------------------- /docker/uvx.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM base 2 | RUN apk add --no-cache python3 coreutils 3 | COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ 4 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "supergateway", 3 | "version": "3.1.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "supergateway", 9 | "version": "3.1.0", 10 | "dependencies": { 11 | "@modelcontextprotocol/sdk": "^1.11.3", 12 | "body-parser": "^1.20.3", 13 | "cors": "^2.8.5", 14 | "express": "^4.21.2", 15 | "uuid": "^11.1.0", 16 | "ws": "^8.18.2", 17 | "yargs": "^17.7.2", 18 | "zod": "^3.24.4" 19 | }, 20 | "bin": { 21 | "supergateway": "dist/index.js" 22 | }, 23 | "devDependencies": { 24 | "@types/body-parser": "^1.19.5", 25 | "@types/cors": "^2.8.18", 26 | "@types/express": "^5.0.2", 27 | "@types/node": "^22.15.18", 28 | "@types/ws": "^8.18.1", 29 | "@types/yargs": "^17.0.33", 30 | "husky": "^9.1.7", 31 | "lint-staged": "^16.0.0", 32 | "prettier": "^3.5.3", 33 | "prev-modelcontextprotocol-sdk": "npm:@modelcontextprotocol/sdk@1.4.0", 34 | "ts-node": "^10.9.2", 35 | "tsx": "^4.19.4", 36 | "typescript": "^5.8.3" 37 | } 38 | }, 39 | "node_modules/@cspotcode/source-map-support": { 40 | "version": "0.8.1", 41 | "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", 42 | "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", 43 | "dev": true, 44 | "dependencies": { 45 | "@jridgewell/trace-mapping": "0.3.9" 46 | }, 47 | "engines": { 48 | "node": ">=12" 49 | } 50 | }, 51 | "node_modules/@esbuild/aix-ppc64": { 52 | "version": "0.25.2", 53 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", 54 | "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", 55 | "cpu": [ 56 | "ppc64" 57 | ], 58 | "dev": true, 59 | "license": "MIT", 60 | "optional": true, 61 | "os": [ 62 | "aix" 63 | ], 64 | "engines": { 65 | "node": ">=18" 66 | } 67 | }, 68 | "node_modules/@esbuild/android-arm": { 69 | "version": "0.25.2", 70 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", 71 | "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", 72 | "cpu": [ 73 | "arm" 74 | ], 75 | "dev": true, 76 | "license": "MIT", 77 | "optional": true, 78 | "os": [ 79 | "android" 80 | ], 81 | "engines": { 82 | "node": ">=18" 83 | } 84 | }, 85 | "node_modules/@esbuild/android-arm64": { 86 | "version": "0.25.2", 87 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", 88 | "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", 89 | "cpu": [ 90 | "arm64" 91 | ], 92 | "dev": true, 93 | "license": "MIT", 94 | "optional": true, 95 | "os": [ 96 | "android" 97 | ], 98 | "engines": { 99 | "node": ">=18" 100 | } 101 | }, 102 | "node_modules/@esbuild/android-x64": { 103 | "version": "0.25.2", 104 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", 105 | "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", 106 | "cpu": [ 107 | "x64" 108 | ], 109 | "dev": true, 110 | "license": "MIT", 111 | "optional": true, 112 | "os": [ 113 | "android" 114 | ], 115 | "engines": { 116 | "node": ">=18" 117 | } 118 | }, 119 | "node_modules/@esbuild/darwin-arm64": { 120 | "version": "0.25.2", 121 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", 122 | "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", 123 | "cpu": [ 124 | "arm64" 125 | ], 126 | "dev": true, 127 | "license": "MIT", 128 | "optional": true, 129 | "os": [ 130 | "darwin" 131 | ], 132 | "engines": { 133 | "node": ">=18" 134 | } 135 | }, 136 | "node_modules/@esbuild/darwin-x64": { 137 | "version": "0.25.2", 138 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", 139 | "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", 140 | "cpu": [ 141 | "x64" 142 | ], 143 | "dev": true, 144 | "license": "MIT", 145 | "optional": true, 146 | "os": [ 147 | "darwin" 148 | ], 149 | "engines": { 150 | "node": ">=18" 151 | } 152 | }, 153 | "node_modules/@esbuild/freebsd-arm64": { 154 | "version": "0.25.2", 155 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", 156 | "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", 157 | "cpu": [ 158 | "arm64" 159 | ], 160 | "dev": true, 161 | "license": "MIT", 162 | "optional": true, 163 | "os": [ 164 | "freebsd" 165 | ], 166 | "engines": { 167 | "node": ">=18" 168 | } 169 | }, 170 | "node_modules/@esbuild/freebsd-x64": { 171 | "version": "0.25.2", 172 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", 173 | "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", 174 | "cpu": [ 175 | "x64" 176 | ], 177 | "dev": true, 178 | "license": "MIT", 179 | "optional": true, 180 | "os": [ 181 | "freebsd" 182 | ], 183 | "engines": { 184 | "node": ">=18" 185 | } 186 | }, 187 | "node_modules/@esbuild/linux-arm": { 188 | "version": "0.25.2", 189 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", 190 | "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", 191 | "cpu": [ 192 | "arm" 193 | ], 194 | "dev": true, 195 | "license": "MIT", 196 | "optional": true, 197 | "os": [ 198 | "linux" 199 | ], 200 | "engines": { 201 | "node": ">=18" 202 | } 203 | }, 204 | "node_modules/@esbuild/linux-arm64": { 205 | "version": "0.25.2", 206 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", 207 | "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", 208 | "cpu": [ 209 | "arm64" 210 | ], 211 | "dev": true, 212 | "license": "MIT", 213 | "optional": true, 214 | "os": [ 215 | "linux" 216 | ], 217 | "engines": { 218 | "node": ">=18" 219 | } 220 | }, 221 | "node_modules/@esbuild/linux-ia32": { 222 | "version": "0.25.2", 223 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", 224 | "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", 225 | "cpu": [ 226 | "ia32" 227 | ], 228 | "dev": true, 229 | "license": "MIT", 230 | "optional": true, 231 | "os": [ 232 | "linux" 233 | ], 234 | "engines": { 235 | "node": ">=18" 236 | } 237 | }, 238 | "node_modules/@esbuild/linux-loong64": { 239 | "version": "0.25.2", 240 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", 241 | "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", 242 | "cpu": [ 243 | "loong64" 244 | ], 245 | "dev": true, 246 | "license": "MIT", 247 | "optional": true, 248 | "os": [ 249 | "linux" 250 | ], 251 | "engines": { 252 | "node": ">=18" 253 | } 254 | }, 255 | "node_modules/@esbuild/linux-mips64el": { 256 | "version": "0.25.2", 257 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", 258 | "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", 259 | "cpu": [ 260 | "mips64el" 261 | ], 262 | "dev": true, 263 | "license": "MIT", 264 | "optional": true, 265 | "os": [ 266 | "linux" 267 | ], 268 | "engines": { 269 | "node": ">=18" 270 | } 271 | }, 272 | "node_modules/@esbuild/linux-ppc64": { 273 | "version": "0.25.2", 274 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", 275 | "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", 276 | "cpu": [ 277 | "ppc64" 278 | ], 279 | "dev": true, 280 | "license": "MIT", 281 | "optional": true, 282 | "os": [ 283 | "linux" 284 | ], 285 | "engines": { 286 | "node": ">=18" 287 | } 288 | }, 289 | "node_modules/@esbuild/linux-riscv64": { 290 | "version": "0.25.2", 291 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", 292 | "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", 293 | "cpu": [ 294 | "riscv64" 295 | ], 296 | "dev": true, 297 | "license": "MIT", 298 | "optional": true, 299 | "os": [ 300 | "linux" 301 | ], 302 | "engines": { 303 | "node": ">=18" 304 | } 305 | }, 306 | "node_modules/@esbuild/linux-s390x": { 307 | "version": "0.25.2", 308 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", 309 | "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", 310 | "cpu": [ 311 | "s390x" 312 | ], 313 | "dev": true, 314 | "license": "MIT", 315 | "optional": true, 316 | "os": [ 317 | "linux" 318 | ], 319 | "engines": { 320 | "node": ">=18" 321 | } 322 | }, 323 | "node_modules/@esbuild/linux-x64": { 324 | "version": "0.25.2", 325 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", 326 | "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", 327 | "cpu": [ 328 | "x64" 329 | ], 330 | "dev": true, 331 | "license": "MIT", 332 | "optional": true, 333 | "os": [ 334 | "linux" 335 | ], 336 | "engines": { 337 | "node": ">=18" 338 | } 339 | }, 340 | "node_modules/@esbuild/netbsd-arm64": { 341 | "version": "0.25.2", 342 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", 343 | "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", 344 | "cpu": [ 345 | "arm64" 346 | ], 347 | "dev": true, 348 | "license": "MIT", 349 | "optional": true, 350 | "os": [ 351 | "netbsd" 352 | ], 353 | "engines": { 354 | "node": ">=18" 355 | } 356 | }, 357 | "node_modules/@esbuild/netbsd-x64": { 358 | "version": "0.25.2", 359 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", 360 | "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", 361 | "cpu": [ 362 | "x64" 363 | ], 364 | "dev": true, 365 | "license": "MIT", 366 | "optional": true, 367 | "os": [ 368 | "netbsd" 369 | ], 370 | "engines": { 371 | "node": ">=18" 372 | } 373 | }, 374 | "node_modules/@esbuild/openbsd-arm64": { 375 | "version": "0.25.2", 376 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", 377 | "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", 378 | "cpu": [ 379 | "arm64" 380 | ], 381 | "dev": true, 382 | "license": "MIT", 383 | "optional": true, 384 | "os": [ 385 | "openbsd" 386 | ], 387 | "engines": { 388 | "node": ">=18" 389 | } 390 | }, 391 | "node_modules/@esbuild/openbsd-x64": { 392 | "version": "0.25.2", 393 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", 394 | "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", 395 | "cpu": [ 396 | "x64" 397 | ], 398 | "dev": true, 399 | "license": "MIT", 400 | "optional": true, 401 | "os": [ 402 | "openbsd" 403 | ], 404 | "engines": { 405 | "node": ">=18" 406 | } 407 | }, 408 | "node_modules/@esbuild/sunos-x64": { 409 | "version": "0.25.2", 410 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", 411 | "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", 412 | "cpu": [ 413 | "x64" 414 | ], 415 | "dev": true, 416 | "license": "MIT", 417 | "optional": true, 418 | "os": [ 419 | "sunos" 420 | ], 421 | "engines": { 422 | "node": ">=18" 423 | } 424 | }, 425 | "node_modules/@esbuild/win32-arm64": { 426 | "version": "0.25.2", 427 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", 428 | "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", 429 | "cpu": [ 430 | "arm64" 431 | ], 432 | "dev": true, 433 | "license": "MIT", 434 | "optional": true, 435 | "os": [ 436 | "win32" 437 | ], 438 | "engines": { 439 | "node": ">=18" 440 | } 441 | }, 442 | "node_modules/@esbuild/win32-ia32": { 443 | "version": "0.25.2", 444 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", 445 | "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", 446 | "cpu": [ 447 | "ia32" 448 | ], 449 | "dev": true, 450 | "license": "MIT", 451 | "optional": true, 452 | "os": [ 453 | "win32" 454 | ], 455 | "engines": { 456 | "node": ">=18" 457 | } 458 | }, 459 | "node_modules/@esbuild/win32-x64": { 460 | "version": "0.25.2", 461 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", 462 | "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", 463 | "cpu": [ 464 | "x64" 465 | ], 466 | "dev": true, 467 | "license": "MIT", 468 | "optional": true, 469 | "os": [ 470 | "win32" 471 | ], 472 | "engines": { 473 | "node": ">=18" 474 | } 475 | }, 476 | "node_modules/@jridgewell/resolve-uri": { 477 | "version": "3.1.2", 478 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 479 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 480 | "dev": true, 481 | "engines": { 482 | "node": ">=6.0.0" 483 | } 484 | }, 485 | "node_modules/@jridgewell/sourcemap-codec": { 486 | "version": "1.5.0", 487 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 488 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 489 | "dev": true 490 | }, 491 | "node_modules/@jridgewell/trace-mapping": { 492 | "version": "0.3.9", 493 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", 494 | "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", 495 | "dev": true, 496 | "dependencies": { 497 | "@jridgewell/resolve-uri": "^3.0.3", 498 | "@jridgewell/sourcemap-codec": "^1.4.10" 499 | } 500 | }, 501 | "node_modules/@modelcontextprotocol/sdk": { 502 | "version": "1.12.0", 503 | "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.12.0.tgz", 504 | "integrity": "sha512-m//7RlINx1F3sz3KqwY1WWzVgTcYX52HYk4bJ1hkBXV3zccAEth+jRvG8DBRrdaQuRsPAJOx2MH3zaHNCKL7Zg==", 505 | "license": "MIT", 506 | "dependencies": { 507 | "ajv": "^6.12.6", 508 | "content-type": "^1.0.5", 509 | "cors": "^2.8.5", 510 | "cross-spawn": "^7.0.5", 511 | "eventsource": "^3.0.2", 512 | "express": "^5.0.1", 513 | "express-rate-limit": "^7.5.0", 514 | "pkce-challenge": "^5.0.0", 515 | "raw-body": "^3.0.0", 516 | "zod": "^3.23.8", 517 | "zod-to-json-schema": "^3.24.1" 518 | }, 519 | "engines": { 520 | "node": ">=18" 521 | } 522 | }, 523 | "node_modules/@modelcontextprotocol/sdk/node_modules/accepts": { 524 | "version": "2.0.0", 525 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", 526 | "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", 527 | "license": "MIT", 528 | "dependencies": { 529 | "mime-types": "^3.0.0", 530 | "negotiator": "^1.0.0" 531 | }, 532 | "engines": { 533 | "node": ">= 0.6" 534 | } 535 | }, 536 | "node_modules/@modelcontextprotocol/sdk/node_modules/body-parser": { 537 | "version": "2.2.0", 538 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", 539 | "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", 540 | "license": "MIT", 541 | "dependencies": { 542 | "bytes": "^3.1.2", 543 | "content-type": "^1.0.5", 544 | "debug": "^4.4.0", 545 | "http-errors": "^2.0.0", 546 | "iconv-lite": "^0.6.3", 547 | "on-finished": "^2.4.1", 548 | "qs": "^6.14.0", 549 | "raw-body": "^3.0.0", 550 | "type-is": "^2.0.0" 551 | }, 552 | "engines": { 553 | "node": ">=18" 554 | } 555 | }, 556 | "node_modules/@modelcontextprotocol/sdk/node_modules/content-disposition": { 557 | "version": "1.0.0", 558 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", 559 | "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", 560 | "license": "MIT", 561 | "dependencies": { 562 | "safe-buffer": "5.2.1" 563 | }, 564 | "engines": { 565 | "node": ">= 0.6" 566 | } 567 | }, 568 | "node_modules/@modelcontextprotocol/sdk/node_modules/cookie-signature": { 569 | "version": "1.2.2", 570 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", 571 | "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", 572 | "license": "MIT", 573 | "engines": { 574 | "node": ">=6.6.0" 575 | } 576 | }, 577 | "node_modules/@modelcontextprotocol/sdk/node_modules/debug": { 578 | "version": "4.4.0", 579 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 580 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 581 | "license": "MIT", 582 | "dependencies": { 583 | "ms": "^2.1.3" 584 | }, 585 | "engines": { 586 | "node": ">=6.0" 587 | }, 588 | "peerDependenciesMeta": { 589 | "supports-color": { 590 | "optional": true 591 | } 592 | } 593 | }, 594 | "node_modules/@modelcontextprotocol/sdk/node_modules/express": { 595 | "version": "5.1.0", 596 | "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", 597 | "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", 598 | "license": "MIT", 599 | "dependencies": { 600 | "accepts": "^2.0.0", 601 | "body-parser": "^2.2.0", 602 | "content-disposition": "^1.0.0", 603 | "content-type": "^1.0.5", 604 | "cookie": "^0.7.1", 605 | "cookie-signature": "^1.2.1", 606 | "debug": "^4.4.0", 607 | "encodeurl": "^2.0.0", 608 | "escape-html": "^1.0.3", 609 | "etag": "^1.8.1", 610 | "finalhandler": "^2.1.0", 611 | "fresh": "^2.0.0", 612 | "http-errors": "^2.0.0", 613 | "merge-descriptors": "^2.0.0", 614 | "mime-types": "^3.0.0", 615 | "on-finished": "^2.4.1", 616 | "once": "^1.4.0", 617 | "parseurl": "^1.3.3", 618 | "proxy-addr": "^2.0.7", 619 | "qs": "^6.14.0", 620 | "range-parser": "^1.2.1", 621 | "router": "^2.2.0", 622 | "send": "^1.1.0", 623 | "serve-static": "^2.2.0", 624 | "statuses": "^2.0.1", 625 | "type-is": "^2.0.1", 626 | "vary": "^1.1.2" 627 | }, 628 | "engines": { 629 | "node": ">= 18" 630 | }, 631 | "funding": { 632 | "type": "opencollective", 633 | "url": "https://opencollective.com/express" 634 | } 635 | }, 636 | "node_modules/@modelcontextprotocol/sdk/node_modules/finalhandler": { 637 | "version": "2.1.0", 638 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", 639 | "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", 640 | "license": "MIT", 641 | "dependencies": { 642 | "debug": "^4.4.0", 643 | "encodeurl": "^2.0.0", 644 | "escape-html": "^1.0.3", 645 | "on-finished": "^2.4.1", 646 | "parseurl": "^1.3.3", 647 | "statuses": "^2.0.1" 648 | }, 649 | "engines": { 650 | "node": ">= 0.8" 651 | } 652 | }, 653 | "node_modules/@modelcontextprotocol/sdk/node_modules/fresh": { 654 | "version": "2.0.0", 655 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", 656 | "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", 657 | "license": "MIT", 658 | "engines": { 659 | "node": ">= 0.8" 660 | } 661 | }, 662 | "node_modules/@modelcontextprotocol/sdk/node_modules/iconv-lite": { 663 | "version": "0.6.3", 664 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 665 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 666 | "license": "MIT", 667 | "dependencies": { 668 | "safer-buffer": ">= 2.1.2 < 3.0.0" 669 | }, 670 | "engines": { 671 | "node": ">=0.10.0" 672 | } 673 | }, 674 | "node_modules/@modelcontextprotocol/sdk/node_modules/media-typer": { 675 | "version": "1.1.0", 676 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", 677 | "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", 678 | "license": "MIT", 679 | "engines": { 680 | "node": ">= 0.8" 681 | } 682 | }, 683 | "node_modules/@modelcontextprotocol/sdk/node_modules/merge-descriptors": { 684 | "version": "2.0.0", 685 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", 686 | "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", 687 | "license": "MIT", 688 | "engines": { 689 | "node": ">=18" 690 | }, 691 | "funding": { 692 | "url": "https://github.com/sponsors/sindresorhus" 693 | } 694 | }, 695 | "node_modules/@modelcontextprotocol/sdk/node_modules/mime-db": { 696 | "version": "1.54.0", 697 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", 698 | "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", 699 | "license": "MIT", 700 | "engines": { 701 | "node": ">= 0.6" 702 | } 703 | }, 704 | "node_modules/@modelcontextprotocol/sdk/node_modules/mime-types": { 705 | "version": "3.0.1", 706 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", 707 | "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", 708 | "license": "MIT", 709 | "dependencies": { 710 | "mime-db": "^1.54.0" 711 | }, 712 | "engines": { 713 | "node": ">= 0.6" 714 | } 715 | }, 716 | "node_modules/@modelcontextprotocol/sdk/node_modules/ms": { 717 | "version": "2.1.3", 718 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 719 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 720 | "license": "MIT" 721 | }, 722 | "node_modules/@modelcontextprotocol/sdk/node_modules/negotiator": { 723 | "version": "1.0.0", 724 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", 725 | "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", 726 | "license": "MIT", 727 | "engines": { 728 | "node": ">= 0.6" 729 | } 730 | }, 731 | "node_modules/@modelcontextprotocol/sdk/node_modules/qs": { 732 | "version": "6.14.0", 733 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", 734 | "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", 735 | "license": "BSD-3-Clause", 736 | "dependencies": { 737 | "side-channel": "^1.1.0" 738 | }, 739 | "engines": { 740 | "node": ">=0.6" 741 | }, 742 | "funding": { 743 | "url": "https://github.com/sponsors/ljharb" 744 | } 745 | }, 746 | "node_modules/@modelcontextprotocol/sdk/node_modules/send": { 747 | "version": "1.2.0", 748 | "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", 749 | "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", 750 | "license": "MIT", 751 | "dependencies": { 752 | "debug": "^4.3.5", 753 | "encodeurl": "^2.0.0", 754 | "escape-html": "^1.0.3", 755 | "etag": "^1.8.1", 756 | "fresh": "^2.0.0", 757 | "http-errors": "^2.0.0", 758 | "mime-types": "^3.0.1", 759 | "ms": "^2.1.3", 760 | "on-finished": "^2.4.1", 761 | "range-parser": "^1.2.1", 762 | "statuses": "^2.0.1" 763 | }, 764 | "engines": { 765 | "node": ">= 18" 766 | } 767 | }, 768 | "node_modules/@modelcontextprotocol/sdk/node_modules/serve-static": { 769 | "version": "2.2.0", 770 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", 771 | "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", 772 | "license": "MIT", 773 | "dependencies": { 774 | "encodeurl": "^2.0.0", 775 | "escape-html": "^1.0.3", 776 | "parseurl": "^1.3.3", 777 | "send": "^1.2.0" 778 | }, 779 | "engines": { 780 | "node": ">= 18" 781 | } 782 | }, 783 | "node_modules/@modelcontextprotocol/sdk/node_modules/type-is": { 784 | "version": "2.0.1", 785 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", 786 | "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", 787 | "license": "MIT", 788 | "dependencies": { 789 | "content-type": "^1.0.5", 790 | "media-typer": "^1.1.0", 791 | "mime-types": "^3.0.0" 792 | }, 793 | "engines": { 794 | "node": ">= 0.6" 795 | } 796 | }, 797 | "node_modules/@tsconfig/node10": { 798 | "version": "1.0.11", 799 | "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", 800 | "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", 801 | "dev": true 802 | }, 803 | "node_modules/@tsconfig/node12": { 804 | "version": "1.0.11", 805 | "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", 806 | "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", 807 | "dev": true 808 | }, 809 | "node_modules/@tsconfig/node14": { 810 | "version": "1.0.3", 811 | "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", 812 | "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", 813 | "dev": true 814 | }, 815 | "node_modules/@tsconfig/node16": { 816 | "version": "1.0.4", 817 | "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", 818 | "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", 819 | "dev": true 820 | }, 821 | "node_modules/@types/body-parser": { 822 | "version": "1.19.5", 823 | "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", 824 | "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", 825 | "dev": true, 826 | "dependencies": { 827 | "@types/connect": "*", 828 | "@types/node": "*" 829 | } 830 | }, 831 | "node_modules/@types/connect": { 832 | "version": "3.4.38", 833 | "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", 834 | "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", 835 | "dev": true, 836 | "dependencies": { 837 | "@types/node": "*" 838 | } 839 | }, 840 | "node_modules/@types/cors": { 841 | "version": "2.8.18", 842 | "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.18.tgz", 843 | "integrity": "sha512-nX3d0sxJW41CqQvfOzVG1NCTXfFDrDWIghCZncpHeWlVFd81zxB/DLhg7avFg6eHLCRX7ckBmoIIcqa++upvJA==", 844 | "dev": true, 845 | "license": "MIT", 846 | "dependencies": { 847 | "@types/node": "*" 848 | } 849 | }, 850 | "node_modules/@types/express": { 851 | "version": "5.0.2", 852 | "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.2.tgz", 853 | "integrity": "sha512-BtjL3ZwbCQriyb0DGw+Rt12qAXPiBTPs815lsUvtt1Grk0vLRMZNMUZ741d5rjk+UQOxfDiBZ3dxpX00vSkK3g==", 854 | "dev": true, 855 | "license": "MIT", 856 | "dependencies": { 857 | "@types/body-parser": "*", 858 | "@types/express-serve-static-core": "^5.0.0", 859 | "@types/serve-static": "*" 860 | } 861 | }, 862 | "node_modules/@types/express-serve-static-core": { 863 | "version": "5.0.6", 864 | "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.6.tgz", 865 | "integrity": "sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==", 866 | "dev": true, 867 | "license": "MIT", 868 | "dependencies": { 869 | "@types/node": "*", 870 | "@types/qs": "*", 871 | "@types/range-parser": "*", 872 | "@types/send": "*" 873 | } 874 | }, 875 | "node_modules/@types/http-errors": { 876 | "version": "2.0.4", 877 | "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", 878 | "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", 879 | "dev": true 880 | }, 881 | "node_modules/@types/mime": { 882 | "version": "1.3.5", 883 | "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", 884 | "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", 885 | "dev": true 886 | }, 887 | "node_modules/@types/node": { 888 | "version": "22.15.18", 889 | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.18.tgz", 890 | "integrity": "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg==", 891 | "dev": true, 892 | "license": "MIT", 893 | "dependencies": { 894 | "undici-types": "~6.21.0" 895 | } 896 | }, 897 | "node_modules/@types/qs": { 898 | "version": "6.9.18", 899 | "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", 900 | "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==", 901 | "dev": true, 902 | "license": "MIT" 903 | }, 904 | "node_modules/@types/range-parser": { 905 | "version": "1.2.7", 906 | "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", 907 | "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", 908 | "dev": true, 909 | "license": "MIT" 910 | }, 911 | "node_modules/@types/send": { 912 | "version": "0.17.4", 913 | "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", 914 | "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", 915 | "dev": true, 916 | "dependencies": { 917 | "@types/mime": "^1", 918 | "@types/node": "*" 919 | } 920 | }, 921 | "node_modules/@types/serve-static": { 922 | "version": "1.15.7", 923 | "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", 924 | "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", 925 | "dev": true, 926 | "dependencies": { 927 | "@types/http-errors": "*", 928 | "@types/node": "*", 929 | "@types/send": "*" 930 | } 931 | }, 932 | "node_modules/@types/ws": { 933 | "version": "8.18.1", 934 | "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", 935 | "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", 936 | "dev": true, 937 | "license": "MIT", 938 | "dependencies": { 939 | "@types/node": "*" 940 | } 941 | }, 942 | "node_modules/@types/yargs": { 943 | "version": "17.0.33", 944 | "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", 945 | "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", 946 | "dev": true, 947 | "dependencies": { 948 | "@types/yargs-parser": "*" 949 | } 950 | }, 951 | "node_modules/@types/yargs-parser": { 952 | "version": "21.0.3", 953 | "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", 954 | "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", 955 | "dev": true 956 | }, 957 | "node_modules/accepts": { 958 | "version": "1.3.8", 959 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 960 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 961 | "dependencies": { 962 | "mime-types": "~2.1.34", 963 | "negotiator": "0.6.3" 964 | }, 965 | "engines": { 966 | "node": ">= 0.6" 967 | } 968 | }, 969 | "node_modules/acorn": { 970 | "version": "8.14.0", 971 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", 972 | "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", 973 | "dev": true, 974 | "bin": { 975 | "acorn": "bin/acorn" 976 | }, 977 | "engines": { 978 | "node": ">=0.4.0" 979 | } 980 | }, 981 | "node_modules/acorn-walk": { 982 | "version": "8.3.4", 983 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", 984 | "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", 985 | "dev": true, 986 | "dependencies": { 987 | "acorn": "^8.11.0" 988 | }, 989 | "engines": { 990 | "node": ">=0.4.0" 991 | } 992 | }, 993 | "node_modules/ajv": { 994 | "version": "6.12.6", 995 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 996 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 997 | "license": "MIT", 998 | "dependencies": { 999 | "fast-deep-equal": "^3.1.1", 1000 | "fast-json-stable-stringify": "^2.0.0", 1001 | "json-schema-traverse": "^0.4.1", 1002 | "uri-js": "^4.2.2" 1003 | }, 1004 | "funding": { 1005 | "type": "github", 1006 | "url": "https://github.com/sponsors/epoberezkin" 1007 | } 1008 | }, 1009 | "node_modules/ansi-escapes": { 1010 | "version": "7.0.0", 1011 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", 1012 | "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", 1013 | "dev": true, 1014 | "license": "MIT", 1015 | "dependencies": { 1016 | "environment": "^1.0.0" 1017 | }, 1018 | "engines": { 1019 | "node": ">=18" 1020 | }, 1021 | "funding": { 1022 | "url": "https://github.com/sponsors/sindresorhus" 1023 | } 1024 | }, 1025 | "node_modules/ansi-regex": { 1026 | "version": "5.0.1", 1027 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1028 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1029 | "engines": { 1030 | "node": ">=8" 1031 | } 1032 | }, 1033 | "node_modules/ansi-styles": { 1034 | "version": "4.3.0", 1035 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1036 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1037 | "dependencies": { 1038 | "color-convert": "^2.0.1" 1039 | }, 1040 | "engines": { 1041 | "node": ">=8" 1042 | }, 1043 | "funding": { 1044 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 1045 | } 1046 | }, 1047 | "node_modules/arg": { 1048 | "version": "4.1.3", 1049 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", 1050 | "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", 1051 | "dev": true 1052 | }, 1053 | "node_modules/array-flatten": { 1054 | "version": "1.1.1", 1055 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 1056 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 1057 | }, 1058 | "node_modules/body-parser": { 1059 | "version": "1.20.3", 1060 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", 1061 | "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", 1062 | "dependencies": { 1063 | "bytes": "3.1.2", 1064 | "content-type": "~1.0.5", 1065 | "debug": "2.6.9", 1066 | "depd": "2.0.0", 1067 | "destroy": "1.2.0", 1068 | "http-errors": "2.0.0", 1069 | "iconv-lite": "0.4.24", 1070 | "on-finished": "2.4.1", 1071 | "qs": "6.13.0", 1072 | "raw-body": "2.5.2", 1073 | "type-is": "~1.6.18", 1074 | "unpipe": "1.0.0" 1075 | }, 1076 | "engines": { 1077 | "node": ">= 0.8", 1078 | "npm": "1.2.8000 || >= 1.4.16" 1079 | } 1080 | }, 1081 | "node_modules/body-parser/node_modules/raw-body": { 1082 | "version": "2.5.2", 1083 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", 1084 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", 1085 | "dependencies": { 1086 | "bytes": "3.1.2", 1087 | "http-errors": "2.0.0", 1088 | "iconv-lite": "0.4.24", 1089 | "unpipe": "1.0.0" 1090 | }, 1091 | "engines": { 1092 | "node": ">= 0.8" 1093 | } 1094 | }, 1095 | "node_modules/braces": { 1096 | "version": "3.0.3", 1097 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 1098 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 1099 | "dev": true, 1100 | "license": "MIT", 1101 | "dependencies": { 1102 | "fill-range": "^7.1.1" 1103 | }, 1104 | "engines": { 1105 | "node": ">=8" 1106 | } 1107 | }, 1108 | "node_modules/bytes": { 1109 | "version": "3.1.2", 1110 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 1111 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 1112 | "engines": { 1113 | "node": ">= 0.8" 1114 | } 1115 | }, 1116 | "node_modules/call-bind-apply-helpers": { 1117 | "version": "1.0.1", 1118 | "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", 1119 | "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", 1120 | "dependencies": { 1121 | "es-errors": "^1.3.0", 1122 | "function-bind": "^1.1.2" 1123 | }, 1124 | "engines": { 1125 | "node": ">= 0.4" 1126 | } 1127 | }, 1128 | "node_modules/call-bound": { 1129 | "version": "1.0.3", 1130 | "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", 1131 | "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", 1132 | "dependencies": { 1133 | "call-bind-apply-helpers": "^1.0.1", 1134 | "get-intrinsic": "^1.2.6" 1135 | }, 1136 | "engines": { 1137 | "node": ">= 0.4" 1138 | }, 1139 | "funding": { 1140 | "url": "https://github.com/sponsors/ljharb" 1141 | } 1142 | }, 1143 | "node_modules/chalk": { 1144 | "version": "5.4.1", 1145 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", 1146 | "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", 1147 | "dev": true, 1148 | "license": "MIT", 1149 | "engines": { 1150 | "node": "^12.17.0 || ^14.13 || >=16.0.0" 1151 | }, 1152 | "funding": { 1153 | "url": "https://github.com/chalk/chalk?sponsor=1" 1154 | } 1155 | }, 1156 | "node_modules/cli-cursor": { 1157 | "version": "5.0.0", 1158 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", 1159 | "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", 1160 | "dev": true, 1161 | "license": "MIT", 1162 | "dependencies": { 1163 | "restore-cursor": "^5.0.0" 1164 | }, 1165 | "engines": { 1166 | "node": ">=18" 1167 | }, 1168 | "funding": { 1169 | "url": "https://github.com/sponsors/sindresorhus" 1170 | } 1171 | }, 1172 | "node_modules/cli-truncate": { 1173 | "version": "4.0.0", 1174 | "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", 1175 | "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", 1176 | "dev": true, 1177 | "license": "MIT", 1178 | "dependencies": { 1179 | "slice-ansi": "^5.0.0", 1180 | "string-width": "^7.0.0" 1181 | }, 1182 | "engines": { 1183 | "node": ">=18" 1184 | }, 1185 | "funding": { 1186 | "url": "https://github.com/sponsors/sindresorhus" 1187 | } 1188 | }, 1189 | "node_modules/cli-truncate/node_modules/ansi-regex": { 1190 | "version": "6.1.0", 1191 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", 1192 | "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", 1193 | "dev": true, 1194 | "license": "MIT", 1195 | "engines": { 1196 | "node": ">=12" 1197 | }, 1198 | "funding": { 1199 | "url": "https://github.com/chalk/ansi-regex?sponsor=1" 1200 | } 1201 | }, 1202 | "node_modules/cli-truncate/node_modules/emoji-regex": { 1203 | "version": "10.4.0", 1204 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", 1205 | "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", 1206 | "dev": true, 1207 | "license": "MIT" 1208 | }, 1209 | "node_modules/cli-truncate/node_modules/string-width": { 1210 | "version": "7.2.0", 1211 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", 1212 | "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", 1213 | "dev": true, 1214 | "license": "MIT", 1215 | "dependencies": { 1216 | "emoji-regex": "^10.3.0", 1217 | "get-east-asian-width": "^1.0.0", 1218 | "strip-ansi": "^7.1.0" 1219 | }, 1220 | "engines": { 1221 | "node": ">=18" 1222 | }, 1223 | "funding": { 1224 | "url": "https://github.com/sponsors/sindresorhus" 1225 | } 1226 | }, 1227 | "node_modules/cli-truncate/node_modules/strip-ansi": { 1228 | "version": "7.1.0", 1229 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", 1230 | "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", 1231 | "dev": true, 1232 | "license": "MIT", 1233 | "dependencies": { 1234 | "ansi-regex": "^6.0.1" 1235 | }, 1236 | "engines": { 1237 | "node": ">=12" 1238 | }, 1239 | "funding": { 1240 | "url": "https://github.com/chalk/strip-ansi?sponsor=1" 1241 | } 1242 | }, 1243 | "node_modules/cliui": { 1244 | "version": "8.0.1", 1245 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", 1246 | "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", 1247 | "dependencies": { 1248 | "string-width": "^4.2.0", 1249 | "strip-ansi": "^6.0.1", 1250 | "wrap-ansi": "^7.0.0" 1251 | }, 1252 | "engines": { 1253 | "node": ">=12" 1254 | } 1255 | }, 1256 | "node_modules/color-convert": { 1257 | "version": "2.0.1", 1258 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1259 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1260 | "dependencies": { 1261 | "color-name": "~1.1.4" 1262 | }, 1263 | "engines": { 1264 | "node": ">=7.0.0" 1265 | } 1266 | }, 1267 | "node_modules/color-name": { 1268 | "version": "1.1.4", 1269 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1270 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 1271 | }, 1272 | "node_modules/colorette": { 1273 | "version": "2.0.20", 1274 | "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", 1275 | "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", 1276 | "dev": true, 1277 | "license": "MIT" 1278 | }, 1279 | "node_modules/commander": { 1280 | "version": "13.1.0", 1281 | "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", 1282 | "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", 1283 | "dev": true, 1284 | "license": "MIT", 1285 | "engines": { 1286 | "node": ">=18" 1287 | } 1288 | }, 1289 | "node_modules/content-disposition": { 1290 | "version": "0.5.4", 1291 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 1292 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 1293 | "dependencies": { 1294 | "safe-buffer": "5.2.1" 1295 | }, 1296 | "engines": { 1297 | "node": ">= 0.6" 1298 | } 1299 | }, 1300 | "node_modules/content-type": { 1301 | "version": "1.0.5", 1302 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 1303 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 1304 | "engines": { 1305 | "node": ">= 0.6" 1306 | } 1307 | }, 1308 | "node_modules/cookie": { 1309 | "version": "0.7.1", 1310 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", 1311 | "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", 1312 | "engines": { 1313 | "node": ">= 0.6" 1314 | } 1315 | }, 1316 | "node_modules/cookie-signature": { 1317 | "version": "1.0.6", 1318 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 1319 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 1320 | }, 1321 | "node_modules/cors": { 1322 | "version": "2.8.5", 1323 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 1324 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 1325 | "license": "MIT", 1326 | "dependencies": { 1327 | "object-assign": "^4", 1328 | "vary": "^1" 1329 | }, 1330 | "engines": { 1331 | "node": ">= 0.10" 1332 | } 1333 | }, 1334 | "node_modules/create-require": { 1335 | "version": "1.1.1", 1336 | "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", 1337 | "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", 1338 | "dev": true 1339 | }, 1340 | "node_modules/cross-spawn": { 1341 | "version": "7.0.6", 1342 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", 1343 | "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", 1344 | "license": "MIT", 1345 | "dependencies": { 1346 | "path-key": "^3.1.0", 1347 | "shebang-command": "^2.0.0", 1348 | "which": "^2.0.1" 1349 | }, 1350 | "engines": { 1351 | "node": ">= 8" 1352 | } 1353 | }, 1354 | "node_modules/debug": { 1355 | "version": "2.6.9", 1356 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1357 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1358 | "dependencies": { 1359 | "ms": "2.0.0" 1360 | } 1361 | }, 1362 | "node_modules/depd": { 1363 | "version": "2.0.0", 1364 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 1365 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 1366 | "engines": { 1367 | "node": ">= 0.8" 1368 | } 1369 | }, 1370 | "node_modules/destroy": { 1371 | "version": "1.2.0", 1372 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 1373 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", 1374 | "engines": { 1375 | "node": ">= 0.8", 1376 | "npm": "1.2.8000 || >= 1.4.16" 1377 | } 1378 | }, 1379 | "node_modules/diff": { 1380 | "version": "4.0.2", 1381 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 1382 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 1383 | "dev": true, 1384 | "engines": { 1385 | "node": ">=0.3.1" 1386 | } 1387 | }, 1388 | "node_modules/dunder-proto": { 1389 | "version": "1.0.1", 1390 | "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 1391 | "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 1392 | "dependencies": { 1393 | "call-bind-apply-helpers": "^1.0.1", 1394 | "es-errors": "^1.3.0", 1395 | "gopd": "^1.2.0" 1396 | }, 1397 | "engines": { 1398 | "node": ">= 0.4" 1399 | } 1400 | }, 1401 | "node_modules/ee-first": { 1402 | "version": "1.1.1", 1403 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 1404 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" 1405 | }, 1406 | "node_modules/emoji-regex": { 1407 | "version": "8.0.0", 1408 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1409 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 1410 | }, 1411 | "node_modules/encodeurl": { 1412 | "version": "2.0.0", 1413 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 1414 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 1415 | "engines": { 1416 | "node": ">= 0.8" 1417 | } 1418 | }, 1419 | "node_modules/environment": { 1420 | "version": "1.1.0", 1421 | "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", 1422 | "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", 1423 | "dev": true, 1424 | "license": "MIT", 1425 | "engines": { 1426 | "node": ">=18" 1427 | }, 1428 | "funding": { 1429 | "url": "https://github.com/sponsors/sindresorhus" 1430 | } 1431 | }, 1432 | "node_modules/es-define-property": { 1433 | "version": "1.0.1", 1434 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 1435 | "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 1436 | "engines": { 1437 | "node": ">= 0.4" 1438 | } 1439 | }, 1440 | "node_modules/es-errors": { 1441 | "version": "1.3.0", 1442 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 1443 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 1444 | "engines": { 1445 | "node": ">= 0.4" 1446 | } 1447 | }, 1448 | "node_modules/es-object-atoms": { 1449 | "version": "1.0.0", 1450 | "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", 1451 | "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", 1452 | "dependencies": { 1453 | "es-errors": "^1.3.0" 1454 | }, 1455 | "engines": { 1456 | "node": ">= 0.4" 1457 | } 1458 | }, 1459 | "node_modules/esbuild": { 1460 | "version": "0.25.2", 1461 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", 1462 | "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", 1463 | "dev": true, 1464 | "hasInstallScript": true, 1465 | "license": "MIT", 1466 | "bin": { 1467 | "esbuild": "bin/esbuild" 1468 | }, 1469 | "engines": { 1470 | "node": ">=18" 1471 | }, 1472 | "optionalDependencies": { 1473 | "@esbuild/aix-ppc64": "0.25.2", 1474 | "@esbuild/android-arm": "0.25.2", 1475 | "@esbuild/android-arm64": "0.25.2", 1476 | "@esbuild/android-x64": "0.25.2", 1477 | "@esbuild/darwin-arm64": "0.25.2", 1478 | "@esbuild/darwin-x64": "0.25.2", 1479 | "@esbuild/freebsd-arm64": "0.25.2", 1480 | "@esbuild/freebsd-x64": "0.25.2", 1481 | "@esbuild/linux-arm": "0.25.2", 1482 | "@esbuild/linux-arm64": "0.25.2", 1483 | "@esbuild/linux-ia32": "0.25.2", 1484 | "@esbuild/linux-loong64": "0.25.2", 1485 | "@esbuild/linux-mips64el": "0.25.2", 1486 | "@esbuild/linux-ppc64": "0.25.2", 1487 | "@esbuild/linux-riscv64": "0.25.2", 1488 | "@esbuild/linux-s390x": "0.25.2", 1489 | "@esbuild/linux-x64": "0.25.2", 1490 | "@esbuild/netbsd-arm64": "0.25.2", 1491 | "@esbuild/netbsd-x64": "0.25.2", 1492 | "@esbuild/openbsd-arm64": "0.25.2", 1493 | "@esbuild/openbsd-x64": "0.25.2", 1494 | "@esbuild/sunos-x64": "0.25.2", 1495 | "@esbuild/win32-arm64": "0.25.2", 1496 | "@esbuild/win32-ia32": "0.25.2", 1497 | "@esbuild/win32-x64": "0.25.2" 1498 | } 1499 | }, 1500 | "node_modules/escalade": { 1501 | "version": "3.2.0", 1502 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", 1503 | "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", 1504 | "engines": { 1505 | "node": ">=6" 1506 | } 1507 | }, 1508 | "node_modules/escape-html": { 1509 | "version": "1.0.3", 1510 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 1511 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 1512 | }, 1513 | "node_modules/etag": { 1514 | "version": "1.8.1", 1515 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 1516 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 1517 | "engines": { 1518 | "node": ">= 0.6" 1519 | } 1520 | }, 1521 | "node_modules/eventemitter3": { 1522 | "version": "5.0.1", 1523 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", 1524 | "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", 1525 | "dev": true, 1526 | "license": "MIT" 1527 | }, 1528 | "node_modules/eventsource": { 1529 | "version": "3.0.5", 1530 | "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.5.tgz", 1531 | "integrity": "sha512-LT/5J605bx5SNyE+ITBDiM3FxffBiq9un7Vx0EwMDM3vg8sWKx/tO2zC+LMqZ+smAM0F2hblaDZUVZF0te2pSw==", 1532 | "license": "MIT", 1533 | "dependencies": { 1534 | "eventsource-parser": "^3.0.0" 1535 | }, 1536 | "engines": { 1537 | "node": ">=18.0.0" 1538 | } 1539 | }, 1540 | "node_modules/eventsource-parser": { 1541 | "version": "3.0.0", 1542 | "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.0.tgz", 1543 | "integrity": "sha512-T1C0XCUimhxVQzW4zFipdx0SficT651NnkR0ZSH3yQwh+mFMdLfgjABVi4YtMTtaL4s168593DaoaRLMqryavA==", 1544 | "license": "MIT", 1545 | "engines": { 1546 | "node": ">=18.0.0" 1547 | } 1548 | }, 1549 | "node_modules/express": { 1550 | "version": "4.21.2", 1551 | "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", 1552 | "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", 1553 | "dependencies": { 1554 | "accepts": "~1.3.8", 1555 | "array-flatten": "1.1.1", 1556 | "body-parser": "1.20.3", 1557 | "content-disposition": "0.5.4", 1558 | "content-type": "~1.0.4", 1559 | "cookie": "0.7.1", 1560 | "cookie-signature": "1.0.6", 1561 | "debug": "2.6.9", 1562 | "depd": "2.0.0", 1563 | "encodeurl": "~2.0.0", 1564 | "escape-html": "~1.0.3", 1565 | "etag": "~1.8.1", 1566 | "finalhandler": "1.3.1", 1567 | "fresh": "0.5.2", 1568 | "http-errors": "2.0.0", 1569 | "merge-descriptors": "1.0.3", 1570 | "methods": "~1.1.2", 1571 | "on-finished": "2.4.1", 1572 | "parseurl": "~1.3.3", 1573 | "path-to-regexp": "0.1.12", 1574 | "proxy-addr": "~2.0.7", 1575 | "qs": "6.13.0", 1576 | "range-parser": "~1.2.1", 1577 | "safe-buffer": "5.2.1", 1578 | "send": "0.19.0", 1579 | "serve-static": "1.16.2", 1580 | "setprototypeof": "1.2.0", 1581 | "statuses": "2.0.1", 1582 | "type-is": "~1.6.18", 1583 | "utils-merge": "1.0.1", 1584 | "vary": "~1.1.2" 1585 | }, 1586 | "engines": { 1587 | "node": ">= 0.10.0" 1588 | }, 1589 | "funding": { 1590 | "type": "opencollective", 1591 | "url": "https://opencollective.com/express" 1592 | } 1593 | }, 1594 | "node_modules/express-rate-limit": { 1595 | "version": "7.5.0", 1596 | "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", 1597 | "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", 1598 | "license": "MIT", 1599 | "engines": { 1600 | "node": ">= 16" 1601 | }, 1602 | "funding": { 1603 | "url": "https://github.com/sponsors/express-rate-limit" 1604 | }, 1605 | "peerDependencies": { 1606 | "express": "^4.11 || 5 || ^5.0.0-beta.1" 1607 | } 1608 | }, 1609 | "node_modules/fast-deep-equal": { 1610 | "version": "3.1.3", 1611 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 1612 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 1613 | "license": "MIT" 1614 | }, 1615 | "node_modules/fast-json-stable-stringify": { 1616 | "version": "2.1.0", 1617 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 1618 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 1619 | "license": "MIT" 1620 | }, 1621 | "node_modules/fill-range": { 1622 | "version": "7.1.1", 1623 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 1624 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 1625 | "dev": true, 1626 | "license": "MIT", 1627 | "dependencies": { 1628 | "to-regex-range": "^5.0.1" 1629 | }, 1630 | "engines": { 1631 | "node": ">=8" 1632 | } 1633 | }, 1634 | "node_modules/finalhandler": { 1635 | "version": "1.3.1", 1636 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", 1637 | "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", 1638 | "dependencies": { 1639 | "debug": "2.6.9", 1640 | "encodeurl": "~2.0.0", 1641 | "escape-html": "~1.0.3", 1642 | "on-finished": "2.4.1", 1643 | "parseurl": "~1.3.3", 1644 | "statuses": "2.0.1", 1645 | "unpipe": "~1.0.0" 1646 | }, 1647 | "engines": { 1648 | "node": ">= 0.8" 1649 | } 1650 | }, 1651 | "node_modules/forwarded": { 1652 | "version": "0.2.0", 1653 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 1654 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 1655 | "engines": { 1656 | "node": ">= 0.6" 1657 | } 1658 | }, 1659 | "node_modules/fresh": { 1660 | "version": "0.5.2", 1661 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 1662 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", 1663 | "engines": { 1664 | "node": ">= 0.6" 1665 | } 1666 | }, 1667 | "node_modules/fsevents": { 1668 | "version": "2.3.3", 1669 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1670 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1671 | "dev": true, 1672 | "hasInstallScript": true, 1673 | "optional": true, 1674 | "os": [ 1675 | "darwin" 1676 | ], 1677 | "engines": { 1678 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1679 | } 1680 | }, 1681 | "node_modules/function-bind": { 1682 | "version": "1.1.2", 1683 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 1684 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 1685 | "funding": { 1686 | "url": "https://github.com/sponsors/ljharb" 1687 | } 1688 | }, 1689 | "node_modules/get-caller-file": { 1690 | "version": "2.0.5", 1691 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 1692 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 1693 | "engines": { 1694 | "node": "6.* || 8.* || >= 10.*" 1695 | } 1696 | }, 1697 | "node_modules/get-east-asian-width": { 1698 | "version": "1.3.0", 1699 | "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", 1700 | "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", 1701 | "dev": true, 1702 | "license": "MIT", 1703 | "engines": { 1704 | "node": ">=18" 1705 | }, 1706 | "funding": { 1707 | "url": "https://github.com/sponsors/sindresorhus" 1708 | } 1709 | }, 1710 | "node_modules/get-intrinsic": { 1711 | "version": "1.2.6", 1712 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", 1713 | "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", 1714 | "dependencies": { 1715 | "call-bind-apply-helpers": "^1.0.1", 1716 | "dunder-proto": "^1.0.0", 1717 | "es-define-property": "^1.0.1", 1718 | "es-errors": "^1.3.0", 1719 | "es-object-atoms": "^1.0.0", 1720 | "function-bind": "^1.1.2", 1721 | "gopd": "^1.2.0", 1722 | "has-symbols": "^1.1.0", 1723 | "hasown": "^2.0.2", 1724 | "math-intrinsics": "^1.0.0" 1725 | }, 1726 | "engines": { 1727 | "node": ">= 0.4" 1728 | }, 1729 | "funding": { 1730 | "url": "https://github.com/sponsors/ljharb" 1731 | } 1732 | }, 1733 | "node_modules/get-tsconfig": { 1734 | "version": "4.8.1", 1735 | "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", 1736 | "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", 1737 | "dev": true, 1738 | "dependencies": { 1739 | "resolve-pkg-maps": "^1.0.0" 1740 | }, 1741 | "funding": { 1742 | "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" 1743 | } 1744 | }, 1745 | "node_modules/gopd": { 1746 | "version": "1.2.0", 1747 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 1748 | "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 1749 | "engines": { 1750 | "node": ">= 0.4" 1751 | }, 1752 | "funding": { 1753 | "url": "https://github.com/sponsors/ljharb" 1754 | } 1755 | }, 1756 | "node_modules/has-symbols": { 1757 | "version": "1.1.0", 1758 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 1759 | "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 1760 | "engines": { 1761 | "node": ">= 0.4" 1762 | }, 1763 | "funding": { 1764 | "url": "https://github.com/sponsors/ljharb" 1765 | } 1766 | }, 1767 | "node_modules/hasown": { 1768 | "version": "2.0.2", 1769 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 1770 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 1771 | "dependencies": { 1772 | "function-bind": "^1.1.2" 1773 | }, 1774 | "engines": { 1775 | "node": ">= 0.4" 1776 | } 1777 | }, 1778 | "node_modules/http-errors": { 1779 | "version": "2.0.0", 1780 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 1781 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 1782 | "dependencies": { 1783 | "depd": "2.0.0", 1784 | "inherits": "2.0.4", 1785 | "setprototypeof": "1.2.0", 1786 | "statuses": "2.0.1", 1787 | "toidentifier": "1.0.1" 1788 | }, 1789 | "engines": { 1790 | "node": ">= 0.8" 1791 | } 1792 | }, 1793 | "node_modules/husky": { 1794 | "version": "9.1.7", 1795 | "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", 1796 | "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", 1797 | "dev": true, 1798 | "license": "MIT", 1799 | "bin": { 1800 | "husky": "bin.js" 1801 | }, 1802 | "engines": { 1803 | "node": ">=18" 1804 | }, 1805 | "funding": { 1806 | "url": "https://github.com/sponsors/typicode" 1807 | } 1808 | }, 1809 | "node_modules/iconv-lite": { 1810 | "version": "0.4.24", 1811 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 1812 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 1813 | "dependencies": { 1814 | "safer-buffer": ">= 2.1.2 < 3" 1815 | }, 1816 | "engines": { 1817 | "node": ">=0.10.0" 1818 | } 1819 | }, 1820 | "node_modules/inherits": { 1821 | "version": "2.0.4", 1822 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1823 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1824 | }, 1825 | "node_modules/ipaddr.js": { 1826 | "version": "1.9.1", 1827 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 1828 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 1829 | "engines": { 1830 | "node": ">= 0.10" 1831 | } 1832 | }, 1833 | "node_modules/is-fullwidth-code-point": { 1834 | "version": "3.0.0", 1835 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1836 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 1837 | "engines": { 1838 | "node": ">=8" 1839 | } 1840 | }, 1841 | "node_modules/is-number": { 1842 | "version": "7.0.0", 1843 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1844 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1845 | "dev": true, 1846 | "license": "MIT", 1847 | "engines": { 1848 | "node": ">=0.12.0" 1849 | } 1850 | }, 1851 | "node_modules/is-promise": { 1852 | "version": "4.0.0", 1853 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", 1854 | "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", 1855 | "license": "MIT" 1856 | }, 1857 | "node_modules/isexe": { 1858 | "version": "2.0.0", 1859 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1860 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 1861 | "license": "ISC" 1862 | }, 1863 | "node_modules/json-schema-traverse": { 1864 | "version": "0.4.1", 1865 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1866 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1867 | "license": "MIT" 1868 | }, 1869 | "node_modules/lilconfig": { 1870 | "version": "3.1.3", 1871 | "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", 1872 | "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", 1873 | "dev": true, 1874 | "license": "MIT", 1875 | "engines": { 1876 | "node": ">=14" 1877 | }, 1878 | "funding": { 1879 | "url": "https://github.com/sponsors/antonk52" 1880 | } 1881 | }, 1882 | "node_modules/lint-staged": { 1883 | "version": "16.0.0", 1884 | "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.0.0.tgz", 1885 | "integrity": "sha512-sUCprePs6/rbx4vKC60Hez6X10HPkpDJaGcy3D1NdwR7g1RcNkWL8q9mJMreOqmHBTs+1sNFp+wOiX9fr+hoOQ==", 1886 | "dev": true, 1887 | "license": "MIT", 1888 | "dependencies": { 1889 | "chalk": "^5.4.1", 1890 | "commander": "^13.1.0", 1891 | "debug": "^4.4.0", 1892 | "lilconfig": "^3.1.3", 1893 | "listr2": "^8.3.3", 1894 | "micromatch": "^4.0.8", 1895 | "nano-spawn": "^1.0.0", 1896 | "pidtree": "^0.6.0", 1897 | "string-argv": "^0.3.2", 1898 | "yaml": "^2.7.1" 1899 | }, 1900 | "bin": { 1901 | "lint-staged": "bin/lint-staged.js" 1902 | }, 1903 | "engines": { 1904 | "node": ">=20.18" 1905 | }, 1906 | "funding": { 1907 | "url": "https://opencollective.com/lint-staged" 1908 | } 1909 | }, 1910 | "node_modules/lint-staged/node_modules/debug": { 1911 | "version": "4.4.0", 1912 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 1913 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 1914 | "dev": true, 1915 | "license": "MIT", 1916 | "dependencies": { 1917 | "ms": "^2.1.3" 1918 | }, 1919 | "engines": { 1920 | "node": ">=6.0" 1921 | }, 1922 | "peerDependenciesMeta": { 1923 | "supports-color": { 1924 | "optional": true 1925 | } 1926 | } 1927 | }, 1928 | "node_modules/lint-staged/node_modules/ms": { 1929 | "version": "2.1.3", 1930 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1931 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1932 | "dev": true, 1933 | "license": "MIT" 1934 | }, 1935 | "node_modules/listr2": { 1936 | "version": "8.3.3", 1937 | "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", 1938 | "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==", 1939 | "dev": true, 1940 | "license": "MIT", 1941 | "dependencies": { 1942 | "cli-truncate": "^4.0.0", 1943 | "colorette": "^2.0.20", 1944 | "eventemitter3": "^5.0.1", 1945 | "log-update": "^6.1.0", 1946 | "rfdc": "^1.4.1", 1947 | "wrap-ansi": "^9.0.0" 1948 | }, 1949 | "engines": { 1950 | "node": ">=18.0.0" 1951 | } 1952 | }, 1953 | "node_modules/listr2/node_modules/ansi-regex": { 1954 | "version": "6.1.0", 1955 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", 1956 | "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", 1957 | "dev": true, 1958 | "license": "MIT", 1959 | "engines": { 1960 | "node": ">=12" 1961 | }, 1962 | "funding": { 1963 | "url": "https://github.com/chalk/ansi-regex?sponsor=1" 1964 | } 1965 | }, 1966 | "node_modules/listr2/node_modules/ansi-styles": { 1967 | "version": "6.2.1", 1968 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", 1969 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", 1970 | "dev": true, 1971 | "license": "MIT", 1972 | "engines": { 1973 | "node": ">=12" 1974 | }, 1975 | "funding": { 1976 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 1977 | } 1978 | }, 1979 | "node_modules/listr2/node_modules/emoji-regex": { 1980 | "version": "10.4.0", 1981 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", 1982 | "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", 1983 | "dev": true, 1984 | "license": "MIT" 1985 | }, 1986 | "node_modules/listr2/node_modules/string-width": { 1987 | "version": "7.2.0", 1988 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", 1989 | "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", 1990 | "dev": true, 1991 | "license": "MIT", 1992 | "dependencies": { 1993 | "emoji-regex": "^10.3.0", 1994 | "get-east-asian-width": "^1.0.0", 1995 | "strip-ansi": "^7.1.0" 1996 | }, 1997 | "engines": { 1998 | "node": ">=18" 1999 | }, 2000 | "funding": { 2001 | "url": "https://github.com/sponsors/sindresorhus" 2002 | } 2003 | }, 2004 | "node_modules/listr2/node_modules/strip-ansi": { 2005 | "version": "7.1.0", 2006 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", 2007 | "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", 2008 | "dev": true, 2009 | "license": "MIT", 2010 | "dependencies": { 2011 | "ansi-regex": "^6.0.1" 2012 | }, 2013 | "engines": { 2014 | "node": ">=12" 2015 | }, 2016 | "funding": { 2017 | "url": "https://github.com/chalk/strip-ansi?sponsor=1" 2018 | } 2019 | }, 2020 | "node_modules/listr2/node_modules/wrap-ansi": { 2021 | "version": "9.0.0", 2022 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", 2023 | "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", 2024 | "dev": true, 2025 | "license": "MIT", 2026 | "dependencies": { 2027 | "ansi-styles": "^6.2.1", 2028 | "string-width": "^7.0.0", 2029 | "strip-ansi": "^7.1.0" 2030 | }, 2031 | "engines": { 2032 | "node": ">=18" 2033 | }, 2034 | "funding": { 2035 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 2036 | } 2037 | }, 2038 | "node_modules/log-update": { 2039 | "version": "6.1.0", 2040 | "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", 2041 | "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", 2042 | "dev": true, 2043 | "license": "MIT", 2044 | "dependencies": { 2045 | "ansi-escapes": "^7.0.0", 2046 | "cli-cursor": "^5.0.0", 2047 | "slice-ansi": "^7.1.0", 2048 | "strip-ansi": "^7.1.0", 2049 | "wrap-ansi": "^9.0.0" 2050 | }, 2051 | "engines": { 2052 | "node": ">=18" 2053 | }, 2054 | "funding": { 2055 | "url": "https://github.com/sponsors/sindresorhus" 2056 | } 2057 | }, 2058 | "node_modules/log-update/node_modules/ansi-regex": { 2059 | "version": "6.1.0", 2060 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", 2061 | "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", 2062 | "dev": true, 2063 | "license": "MIT", 2064 | "engines": { 2065 | "node": ">=12" 2066 | }, 2067 | "funding": { 2068 | "url": "https://github.com/chalk/ansi-regex?sponsor=1" 2069 | } 2070 | }, 2071 | "node_modules/log-update/node_modules/ansi-styles": { 2072 | "version": "6.2.1", 2073 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", 2074 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", 2075 | "dev": true, 2076 | "license": "MIT", 2077 | "engines": { 2078 | "node": ">=12" 2079 | }, 2080 | "funding": { 2081 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 2082 | } 2083 | }, 2084 | "node_modules/log-update/node_modules/emoji-regex": { 2085 | "version": "10.4.0", 2086 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", 2087 | "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", 2088 | "dev": true, 2089 | "license": "MIT" 2090 | }, 2091 | "node_modules/log-update/node_modules/is-fullwidth-code-point": { 2092 | "version": "5.0.0", 2093 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", 2094 | "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", 2095 | "dev": true, 2096 | "license": "MIT", 2097 | "dependencies": { 2098 | "get-east-asian-width": "^1.0.0" 2099 | }, 2100 | "engines": { 2101 | "node": ">=18" 2102 | }, 2103 | "funding": { 2104 | "url": "https://github.com/sponsors/sindresorhus" 2105 | } 2106 | }, 2107 | "node_modules/log-update/node_modules/slice-ansi": { 2108 | "version": "7.1.0", 2109 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", 2110 | "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", 2111 | "dev": true, 2112 | "license": "MIT", 2113 | "dependencies": { 2114 | "ansi-styles": "^6.2.1", 2115 | "is-fullwidth-code-point": "^5.0.0" 2116 | }, 2117 | "engines": { 2118 | "node": ">=18" 2119 | }, 2120 | "funding": { 2121 | "url": "https://github.com/chalk/slice-ansi?sponsor=1" 2122 | } 2123 | }, 2124 | "node_modules/log-update/node_modules/string-width": { 2125 | "version": "7.2.0", 2126 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", 2127 | "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", 2128 | "dev": true, 2129 | "license": "MIT", 2130 | "dependencies": { 2131 | "emoji-regex": "^10.3.0", 2132 | "get-east-asian-width": "^1.0.0", 2133 | "strip-ansi": "^7.1.0" 2134 | }, 2135 | "engines": { 2136 | "node": ">=18" 2137 | }, 2138 | "funding": { 2139 | "url": "https://github.com/sponsors/sindresorhus" 2140 | } 2141 | }, 2142 | "node_modules/log-update/node_modules/strip-ansi": { 2143 | "version": "7.1.0", 2144 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", 2145 | "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", 2146 | "dev": true, 2147 | "license": "MIT", 2148 | "dependencies": { 2149 | "ansi-regex": "^6.0.1" 2150 | }, 2151 | "engines": { 2152 | "node": ">=12" 2153 | }, 2154 | "funding": { 2155 | "url": "https://github.com/chalk/strip-ansi?sponsor=1" 2156 | } 2157 | }, 2158 | "node_modules/log-update/node_modules/wrap-ansi": { 2159 | "version": "9.0.0", 2160 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", 2161 | "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", 2162 | "dev": true, 2163 | "license": "MIT", 2164 | "dependencies": { 2165 | "ansi-styles": "^6.2.1", 2166 | "string-width": "^7.0.0", 2167 | "strip-ansi": "^7.1.0" 2168 | }, 2169 | "engines": { 2170 | "node": ">=18" 2171 | }, 2172 | "funding": { 2173 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 2174 | } 2175 | }, 2176 | "node_modules/make-error": { 2177 | "version": "1.3.6", 2178 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", 2179 | "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", 2180 | "dev": true 2181 | }, 2182 | "node_modules/math-intrinsics": { 2183 | "version": "1.1.0", 2184 | "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 2185 | "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 2186 | "engines": { 2187 | "node": ">= 0.4" 2188 | } 2189 | }, 2190 | "node_modules/media-typer": { 2191 | "version": "0.3.0", 2192 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 2193 | "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", 2194 | "engines": { 2195 | "node": ">= 0.6" 2196 | } 2197 | }, 2198 | "node_modules/merge-descriptors": { 2199 | "version": "1.0.3", 2200 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", 2201 | "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", 2202 | "funding": { 2203 | "url": "https://github.com/sponsors/sindresorhus" 2204 | } 2205 | }, 2206 | "node_modules/methods": { 2207 | "version": "1.1.2", 2208 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 2209 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", 2210 | "engines": { 2211 | "node": ">= 0.6" 2212 | } 2213 | }, 2214 | "node_modules/micromatch": { 2215 | "version": "4.0.8", 2216 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", 2217 | "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", 2218 | "dev": true, 2219 | "license": "MIT", 2220 | "dependencies": { 2221 | "braces": "^3.0.3", 2222 | "picomatch": "^2.3.1" 2223 | }, 2224 | "engines": { 2225 | "node": ">=8.6" 2226 | } 2227 | }, 2228 | "node_modules/mime": { 2229 | "version": "1.6.0", 2230 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 2231 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 2232 | "bin": { 2233 | "mime": "cli.js" 2234 | }, 2235 | "engines": { 2236 | "node": ">=4" 2237 | } 2238 | }, 2239 | "node_modules/mime-db": { 2240 | "version": "1.52.0", 2241 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 2242 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 2243 | "engines": { 2244 | "node": ">= 0.6" 2245 | } 2246 | }, 2247 | "node_modules/mime-types": { 2248 | "version": "2.1.35", 2249 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 2250 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 2251 | "dependencies": { 2252 | "mime-db": "1.52.0" 2253 | }, 2254 | "engines": { 2255 | "node": ">= 0.6" 2256 | } 2257 | }, 2258 | "node_modules/mimic-function": { 2259 | "version": "5.0.1", 2260 | "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", 2261 | "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", 2262 | "dev": true, 2263 | "license": "MIT", 2264 | "engines": { 2265 | "node": ">=18" 2266 | }, 2267 | "funding": { 2268 | "url": "https://github.com/sponsors/sindresorhus" 2269 | } 2270 | }, 2271 | "node_modules/ms": { 2272 | "version": "2.0.0", 2273 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 2274 | "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" 2275 | }, 2276 | "node_modules/nano-spawn": { 2277 | "version": "1.0.1", 2278 | "resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-1.0.1.tgz", 2279 | "integrity": "sha512-BfcvzBlUTxSDWfT+oH7vd6CbUV+rThLLHCIym/QO6GGLBsyVXleZs00fto2i2jzC/wPiBYk5jyOmpXWg4YopiA==", 2280 | "dev": true, 2281 | "license": "MIT", 2282 | "engines": { 2283 | "node": ">=20.18" 2284 | }, 2285 | "funding": { 2286 | "url": "https://github.com/sindresorhus/nano-spawn?sponsor=1" 2287 | } 2288 | }, 2289 | "node_modules/negotiator": { 2290 | "version": "0.6.3", 2291 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 2292 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 2293 | "engines": { 2294 | "node": ">= 0.6" 2295 | } 2296 | }, 2297 | "node_modules/object-assign": { 2298 | "version": "4.1.1", 2299 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 2300 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 2301 | "license": "MIT", 2302 | "engines": { 2303 | "node": ">=0.10.0" 2304 | } 2305 | }, 2306 | "node_modules/object-inspect": { 2307 | "version": "1.13.3", 2308 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", 2309 | "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", 2310 | "engines": { 2311 | "node": ">= 0.4" 2312 | }, 2313 | "funding": { 2314 | "url": "https://github.com/sponsors/ljharb" 2315 | } 2316 | }, 2317 | "node_modules/on-finished": { 2318 | "version": "2.4.1", 2319 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 2320 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 2321 | "dependencies": { 2322 | "ee-first": "1.1.1" 2323 | }, 2324 | "engines": { 2325 | "node": ">= 0.8" 2326 | } 2327 | }, 2328 | "node_modules/once": { 2329 | "version": "1.4.0", 2330 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 2331 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 2332 | "license": "ISC", 2333 | "dependencies": { 2334 | "wrappy": "1" 2335 | } 2336 | }, 2337 | "node_modules/onetime": { 2338 | "version": "7.0.0", 2339 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", 2340 | "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", 2341 | "dev": true, 2342 | "license": "MIT", 2343 | "dependencies": { 2344 | "mimic-function": "^5.0.0" 2345 | }, 2346 | "engines": { 2347 | "node": ">=18" 2348 | }, 2349 | "funding": { 2350 | "url": "https://github.com/sponsors/sindresorhus" 2351 | } 2352 | }, 2353 | "node_modules/parseurl": { 2354 | "version": "1.3.3", 2355 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 2356 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 2357 | "engines": { 2358 | "node": ">= 0.8" 2359 | } 2360 | }, 2361 | "node_modules/path-key": { 2362 | "version": "3.1.1", 2363 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 2364 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 2365 | "license": "MIT", 2366 | "engines": { 2367 | "node": ">=8" 2368 | } 2369 | }, 2370 | "node_modules/path-to-regexp": { 2371 | "version": "0.1.12", 2372 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", 2373 | "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" 2374 | }, 2375 | "node_modules/picomatch": { 2376 | "version": "2.3.1", 2377 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 2378 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 2379 | "dev": true, 2380 | "license": "MIT", 2381 | "engines": { 2382 | "node": ">=8.6" 2383 | }, 2384 | "funding": { 2385 | "url": "https://github.com/sponsors/jonschlinkert" 2386 | } 2387 | }, 2388 | "node_modules/pidtree": { 2389 | "version": "0.6.0", 2390 | "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", 2391 | "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", 2392 | "dev": true, 2393 | "license": "MIT", 2394 | "bin": { 2395 | "pidtree": "bin/pidtree.js" 2396 | }, 2397 | "engines": { 2398 | "node": ">=0.10" 2399 | } 2400 | }, 2401 | "node_modules/pkce-challenge": { 2402 | "version": "5.0.0", 2403 | "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", 2404 | "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", 2405 | "license": "MIT", 2406 | "engines": { 2407 | "node": ">=16.20.0" 2408 | } 2409 | }, 2410 | "node_modules/prettier": { 2411 | "version": "3.5.3", 2412 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", 2413 | "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", 2414 | "dev": true, 2415 | "license": "MIT", 2416 | "bin": { 2417 | "prettier": "bin/prettier.cjs" 2418 | }, 2419 | "engines": { 2420 | "node": ">=14" 2421 | }, 2422 | "funding": { 2423 | "url": "https://github.com/prettier/prettier?sponsor=1" 2424 | } 2425 | }, 2426 | "node_modules/prev-modelcontextprotocol-sdk": { 2427 | "name": "@modelcontextprotocol/sdk", 2428 | "version": "1.4.0", 2429 | "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.4.0.tgz", 2430 | "integrity": "sha512-50YTsT4H9PuqmgwXkr/BPl0ankfEfxqVtFG8I378XqUThasnYRdNwE2PqktiJNm5MncOf3s5q37juv6kMe6WZQ==", 2431 | "dev": true, 2432 | "license": "MIT", 2433 | "dependencies": { 2434 | "content-type": "^1.0.5", 2435 | "eventsource": "^3.0.2", 2436 | "raw-body": "^3.0.0", 2437 | "zod": "^3.23.8", 2438 | "zod-to-json-schema": "^3.24.1" 2439 | }, 2440 | "engines": { 2441 | "node": ">=18" 2442 | } 2443 | }, 2444 | "node_modules/proxy-addr": { 2445 | "version": "2.0.7", 2446 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 2447 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 2448 | "dependencies": { 2449 | "forwarded": "0.2.0", 2450 | "ipaddr.js": "1.9.1" 2451 | }, 2452 | "engines": { 2453 | "node": ">= 0.10" 2454 | } 2455 | }, 2456 | "node_modules/punycode": { 2457 | "version": "2.3.1", 2458 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", 2459 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", 2460 | "license": "MIT", 2461 | "engines": { 2462 | "node": ">=6" 2463 | } 2464 | }, 2465 | "node_modules/qs": { 2466 | "version": "6.13.0", 2467 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", 2468 | "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", 2469 | "dependencies": { 2470 | "side-channel": "^1.0.6" 2471 | }, 2472 | "engines": { 2473 | "node": ">=0.6" 2474 | }, 2475 | "funding": { 2476 | "url": "https://github.com/sponsors/ljharb" 2477 | } 2478 | }, 2479 | "node_modules/range-parser": { 2480 | "version": "1.2.1", 2481 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 2482 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 2483 | "engines": { 2484 | "node": ">= 0.6" 2485 | } 2486 | }, 2487 | "node_modules/raw-body": { 2488 | "version": "3.0.0", 2489 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", 2490 | "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", 2491 | "dependencies": { 2492 | "bytes": "3.1.2", 2493 | "http-errors": "2.0.0", 2494 | "iconv-lite": "0.6.3", 2495 | "unpipe": "1.0.0" 2496 | }, 2497 | "engines": { 2498 | "node": ">= 0.8" 2499 | } 2500 | }, 2501 | "node_modules/raw-body/node_modules/iconv-lite": { 2502 | "version": "0.6.3", 2503 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 2504 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 2505 | "dependencies": { 2506 | "safer-buffer": ">= 2.1.2 < 3.0.0" 2507 | }, 2508 | "engines": { 2509 | "node": ">=0.10.0" 2510 | } 2511 | }, 2512 | "node_modules/require-directory": { 2513 | "version": "2.1.1", 2514 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 2515 | "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", 2516 | "engines": { 2517 | "node": ">=0.10.0" 2518 | } 2519 | }, 2520 | "node_modules/resolve-pkg-maps": { 2521 | "version": "1.0.0", 2522 | "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", 2523 | "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", 2524 | "dev": true, 2525 | "funding": { 2526 | "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" 2527 | } 2528 | }, 2529 | "node_modules/restore-cursor": { 2530 | "version": "5.1.0", 2531 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", 2532 | "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", 2533 | "dev": true, 2534 | "license": "MIT", 2535 | "dependencies": { 2536 | "onetime": "^7.0.0", 2537 | "signal-exit": "^4.1.0" 2538 | }, 2539 | "engines": { 2540 | "node": ">=18" 2541 | }, 2542 | "funding": { 2543 | "url": "https://github.com/sponsors/sindresorhus" 2544 | } 2545 | }, 2546 | "node_modules/rfdc": { 2547 | "version": "1.4.1", 2548 | "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", 2549 | "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", 2550 | "dev": true, 2551 | "license": "MIT" 2552 | }, 2553 | "node_modules/router": { 2554 | "version": "2.2.0", 2555 | "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", 2556 | "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", 2557 | "license": "MIT", 2558 | "dependencies": { 2559 | "debug": "^4.4.0", 2560 | "depd": "^2.0.0", 2561 | "is-promise": "^4.0.0", 2562 | "parseurl": "^1.3.3", 2563 | "path-to-regexp": "^8.0.0" 2564 | }, 2565 | "engines": { 2566 | "node": ">= 18" 2567 | } 2568 | }, 2569 | "node_modules/router/node_modules/debug": { 2570 | "version": "4.4.0", 2571 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 2572 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 2573 | "license": "MIT", 2574 | "dependencies": { 2575 | "ms": "^2.1.3" 2576 | }, 2577 | "engines": { 2578 | "node": ">=6.0" 2579 | }, 2580 | "peerDependenciesMeta": { 2581 | "supports-color": { 2582 | "optional": true 2583 | } 2584 | } 2585 | }, 2586 | "node_modules/router/node_modules/ms": { 2587 | "version": "2.1.3", 2588 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 2589 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 2590 | "license": "MIT" 2591 | }, 2592 | "node_modules/router/node_modules/path-to-regexp": { 2593 | "version": "8.2.0", 2594 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", 2595 | "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", 2596 | "license": "MIT", 2597 | "engines": { 2598 | "node": ">=16" 2599 | } 2600 | }, 2601 | "node_modules/safe-buffer": { 2602 | "version": "5.2.1", 2603 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 2604 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 2605 | "funding": [ 2606 | { 2607 | "type": "github", 2608 | "url": "https://github.com/sponsors/feross" 2609 | }, 2610 | { 2611 | "type": "patreon", 2612 | "url": "https://www.patreon.com/feross" 2613 | }, 2614 | { 2615 | "type": "consulting", 2616 | "url": "https://feross.org/support" 2617 | } 2618 | ] 2619 | }, 2620 | "node_modules/safer-buffer": { 2621 | "version": "2.1.2", 2622 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 2623 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 2624 | }, 2625 | "node_modules/send": { 2626 | "version": "0.19.0", 2627 | "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", 2628 | "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", 2629 | "dependencies": { 2630 | "debug": "2.6.9", 2631 | "depd": "2.0.0", 2632 | "destroy": "1.2.0", 2633 | "encodeurl": "~1.0.2", 2634 | "escape-html": "~1.0.3", 2635 | "etag": "~1.8.1", 2636 | "fresh": "0.5.2", 2637 | "http-errors": "2.0.0", 2638 | "mime": "1.6.0", 2639 | "ms": "2.1.3", 2640 | "on-finished": "2.4.1", 2641 | "range-parser": "~1.2.1", 2642 | "statuses": "2.0.1" 2643 | }, 2644 | "engines": { 2645 | "node": ">= 0.8.0" 2646 | } 2647 | }, 2648 | "node_modules/send/node_modules/encodeurl": { 2649 | "version": "1.0.2", 2650 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 2651 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", 2652 | "engines": { 2653 | "node": ">= 0.8" 2654 | } 2655 | }, 2656 | "node_modules/send/node_modules/ms": { 2657 | "version": "2.1.3", 2658 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 2659 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 2660 | }, 2661 | "node_modules/serve-static": { 2662 | "version": "1.16.2", 2663 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", 2664 | "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", 2665 | "dependencies": { 2666 | "encodeurl": "~2.0.0", 2667 | "escape-html": "~1.0.3", 2668 | "parseurl": "~1.3.3", 2669 | "send": "0.19.0" 2670 | }, 2671 | "engines": { 2672 | "node": ">= 0.8.0" 2673 | } 2674 | }, 2675 | "node_modules/setprototypeof": { 2676 | "version": "1.2.0", 2677 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 2678 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 2679 | }, 2680 | "node_modules/shebang-command": { 2681 | "version": "2.0.0", 2682 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 2683 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 2684 | "license": "MIT", 2685 | "dependencies": { 2686 | "shebang-regex": "^3.0.0" 2687 | }, 2688 | "engines": { 2689 | "node": ">=8" 2690 | } 2691 | }, 2692 | "node_modules/shebang-regex": { 2693 | "version": "3.0.0", 2694 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 2695 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 2696 | "license": "MIT", 2697 | "engines": { 2698 | "node": ">=8" 2699 | } 2700 | }, 2701 | "node_modules/side-channel": { 2702 | "version": "1.1.0", 2703 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", 2704 | "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", 2705 | "dependencies": { 2706 | "es-errors": "^1.3.0", 2707 | "object-inspect": "^1.13.3", 2708 | "side-channel-list": "^1.0.0", 2709 | "side-channel-map": "^1.0.1", 2710 | "side-channel-weakmap": "^1.0.2" 2711 | }, 2712 | "engines": { 2713 | "node": ">= 0.4" 2714 | }, 2715 | "funding": { 2716 | "url": "https://github.com/sponsors/ljharb" 2717 | } 2718 | }, 2719 | "node_modules/side-channel-list": { 2720 | "version": "1.0.0", 2721 | "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", 2722 | "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", 2723 | "dependencies": { 2724 | "es-errors": "^1.3.0", 2725 | "object-inspect": "^1.13.3" 2726 | }, 2727 | "engines": { 2728 | "node": ">= 0.4" 2729 | }, 2730 | "funding": { 2731 | "url": "https://github.com/sponsors/ljharb" 2732 | } 2733 | }, 2734 | "node_modules/side-channel-map": { 2735 | "version": "1.0.1", 2736 | "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", 2737 | "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", 2738 | "dependencies": { 2739 | "call-bound": "^1.0.2", 2740 | "es-errors": "^1.3.0", 2741 | "get-intrinsic": "^1.2.5", 2742 | "object-inspect": "^1.13.3" 2743 | }, 2744 | "engines": { 2745 | "node": ">= 0.4" 2746 | }, 2747 | "funding": { 2748 | "url": "https://github.com/sponsors/ljharb" 2749 | } 2750 | }, 2751 | "node_modules/side-channel-weakmap": { 2752 | "version": "1.0.2", 2753 | "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", 2754 | "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", 2755 | "dependencies": { 2756 | "call-bound": "^1.0.2", 2757 | "es-errors": "^1.3.0", 2758 | "get-intrinsic": "^1.2.5", 2759 | "object-inspect": "^1.13.3", 2760 | "side-channel-map": "^1.0.1" 2761 | }, 2762 | "engines": { 2763 | "node": ">= 0.4" 2764 | }, 2765 | "funding": { 2766 | "url": "https://github.com/sponsors/ljharb" 2767 | } 2768 | }, 2769 | "node_modules/signal-exit": { 2770 | "version": "4.1.0", 2771 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", 2772 | "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", 2773 | "dev": true, 2774 | "license": "ISC", 2775 | "engines": { 2776 | "node": ">=14" 2777 | }, 2778 | "funding": { 2779 | "url": "https://github.com/sponsors/isaacs" 2780 | } 2781 | }, 2782 | "node_modules/slice-ansi": { 2783 | "version": "5.0.0", 2784 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", 2785 | "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", 2786 | "dev": true, 2787 | "license": "MIT", 2788 | "dependencies": { 2789 | "ansi-styles": "^6.0.0", 2790 | "is-fullwidth-code-point": "^4.0.0" 2791 | }, 2792 | "engines": { 2793 | "node": ">=12" 2794 | }, 2795 | "funding": { 2796 | "url": "https://github.com/chalk/slice-ansi?sponsor=1" 2797 | } 2798 | }, 2799 | "node_modules/slice-ansi/node_modules/ansi-styles": { 2800 | "version": "6.2.1", 2801 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", 2802 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", 2803 | "dev": true, 2804 | "license": "MIT", 2805 | "engines": { 2806 | "node": ">=12" 2807 | }, 2808 | "funding": { 2809 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 2810 | } 2811 | }, 2812 | "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { 2813 | "version": "4.0.0", 2814 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", 2815 | "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", 2816 | "dev": true, 2817 | "license": "MIT", 2818 | "engines": { 2819 | "node": ">=12" 2820 | }, 2821 | "funding": { 2822 | "url": "https://github.com/sponsors/sindresorhus" 2823 | } 2824 | }, 2825 | "node_modules/statuses": { 2826 | "version": "2.0.1", 2827 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 2828 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 2829 | "engines": { 2830 | "node": ">= 0.8" 2831 | } 2832 | }, 2833 | "node_modules/string-argv": { 2834 | "version": "0.3.2", 2835 | "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", 2836 | "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", 2837 | "dev": true, 2838 | "license": "MIT", 2839 | "engines": { 2840 | "node": ">=0.6.19" 2841 | } 2842 | }, 2843 | "node_modules/string-width": { 2844 | "version": "4.2.3", 2845 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 2846 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 2847 | "dependencies": { 2848 | "emoji-regex": "^8.0.0", 2849 | "is-fullwidth-code-point": "^3.0.0", 2850 | "strip-ansi": "^6.0.1" 2851 | }, 2852 | "engines": { 2853 | "node": ">=8" 2854 | } 2855 | }, 2856 | "node_modules/strip-ansi": { 2857 | "version": "6.0.1", 2858 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2859 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2860 | "dependencies": { 2861 | "ansi-regex": "^5.0.1" 2862 | }, 2863 | "engines": { 2864 | "node": ">=8" 2865 | } 2866 | }, 2867 | "node_modules/to-regex-range": { 2868 | "version": "5.0.1", 2869 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2870 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2871 | "dev": true, 2872 | "license": "MIT", 2873 | "dependencies": { 2874 | "is-number": "^7.0.0" 2875 | }, 2876 | "engines": { 2877 | "node": ">=8.0" 2878 | } 2879 | }, 2880 | "node_modules/toidentifier": { 2881 | "version": "1.0.1", 2882 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 2883 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 2884 | "engines": { 2885 | "node": ">=0.6" 2886 | } 2887 | }, 2888 | "node_modules/ts-node": { 2889 | "version": "10.9.2", 2890 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", 2891 | "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", 2892 | "dev": true, 2893 | "dependencies": { 2894 | "@cspotcode/source-map-support": "^0.8.0", 2895 | "@tsconfig/node10": "^1.0.7", 2896 | "@tsconfig/node12": "^1.0.7", 2897 | "@tsconfig/node14": "^1.0.0", 2898 | "@tsconfig/node16": "^1.0.2", 2899 | "acorn": "^8.4.1", 2900 | "acorn-walk": "^8.1.1", 2901 | "arg": "^4.1.0", 2902 | "create-require": "^1.1.0", 2903 | "diff": "^4.0.1", 2904 | "make-error": "^1.1.1", 2905 | "v8-compile-cache-lib": "^3.0.1", 2906 | "yn": "3.1.1" 2907 | }, 2908 | "bin": { 2909 | "ts-node": "dist/bin.js", 2910 | "ts-node-cwd": "dist/bin-cwd.js", 2911 | "ts-node-esm": "dist/bin-esm.js", 2912 | "ts-node-script": "dist/bin-script.js", 2913 | "ts-node-transpile-only": "dist/bin-transpile.js", 2914 | "ts-script": "dist/bin-script-deprecated.js" 2915 | }, 2916 | "peerDependencies": { 2917 | "@swc/core": ">=1.2.50", 2918 | "@swc/wasm": ">=1.2.50", 2919 | "@types/node": "*", 2920 | "typescript": ">=2.7" 2921 | }, 2922 | "peerDependenciesMeta": { 2923 | "@swc/core": { 2924 | "optional": true 2925 | }, 2926 | "@swc/wasm": { 2927 | "optional": true 2928 | } 2929 | } 2930 | }, 2931 | "node_modules/tsx": { 2932 | "version": "4.19.4", 2933 | "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.4.tgz", 2934 | "integrity": "sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==", 2935 | "dev": true, 2936 | "license": "MIT", 2937 | "dependencies": { 2938 | "esbuild": "~0.25.0", 2939 | "get-tsconfig": "^4.7.5" 2940 | }, 2941 | "bin": { 2942 | "tsx": "dist/cli.mjs" 2943 | }, 2944 | "engines": { 2945 | "node": ">=18.0.0" 2946 | }, 2947 | "optionalDependencies": { 2948 | "fsevents": "~2.3.3" 2949 | } 2950 | }, 2951 | "node_modules/type-is": { 2952 | "version": "1.6.18", 2953 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 2954 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 2955 | "dependencies": { 2956 | "media-typer": "0.3.0", 2957 | "mime-types": "~2.1.24" 2958 | }, 2959 | "engines": { 2960 | "node": ">= 0.6" 2961 | } 2962 | }, 2963 | "node_modules/typescript": { 2964 | "version": "5.8.3", 2965 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", 2966 | "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", 2967 | "dev": true, 2968 | "license": "Apache-2.0", 2969 | "bin": { 2970 | "tsc": "bin/tsc", 2971 | "tsserver": "bin/tsserver" 2972 | }, 2973 | "engines": { 2974 | "node": ">=14.17" 2975 | } 2976 | }, 2977 | "node_modules/undici-types": { 2978 | "version": "6.21.0", 2979 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", 2980 | "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", 2981 | "dev": true, 2982 | "license": "MIT" 2983 | }, 2984 | "node_modules/unpipe": { 2985 | "version": "1.0.0", 2986 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 2987 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 2988 | "engines": { 2989 | "node": ">= 0.8" 2990 | } 2991 | }, 2992 | "node_modules/uri-js": { 2993 | "version": "4.4.1", 2994 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 2995 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 2996 | "license": "BSD-2-Clause", 2997 | "dependencies": { 2998 | "punycode": "^2.1.0" 2999 | } 3000 | }, 3001 | "node_modules/utils-merge": { 3002 | "version": "1.0.1", 3003 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 3004 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", 3005 | "engines": { 3006 | "node": ">= 0.4.0" 3007 | } 3008 | }, 3009 | "node_modules/uuid": { 3010 | "version": "11.1.0", 3011 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", 3012 | "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", 3013 | "funding": [ 3014 | "https://github.com/sponsors/broofa", 3015 | "https://github.com/sponsors/ctavan" 3016 | ], 3017 | "license": "MIT", 3018 | "bin": { 3019 | "uuid": "dist/esm/bin/uuid" 3020 | } 3021 | }, 3022 | "node_modules/v8-compile-cache-lib": { 3023 | "version": "3.0.1", 3024 | "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", 3025 | "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", 3026 | "dev": true 3027 | }, 3028 | "node_modules/vary": { 3029 | "version": "1.1.2", 3030 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 3031 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 3032 | "engines": { 3033 | "node": ">= 0.8" 3034 | } 3035 | }, 3036 | "node_modules/which": { 3037 | "version": "2.0.2", 3038 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 3039 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 3040 | "license": "ISC", 3041 | "dependencies": { 3042 | "isexe": "^2.0.0" 3043 | }, 3044 | "bin": { 3045 | "node-which": "bin/node-which" 3046 | }, 3047 | "engines": { 3048 | "node": ">= 8" 3049 | } 3050 | }, 3051 | "node_modules/wrap-ansi": { 3052 | "version": "7.0.0", 3053 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 3054 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 3055 | "dependencies": { 3056 | "ansi-styles": "^4.0.0", 3057 | "string-width": "^4.1.0", 3058 | "strip-ansi": "^6.0.0" 3059 | }, 3060 | "engines": { 3061 | "node": ">=10" 3062 | }, 3063 | "funding": { 3064 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 3065 | } 3066 | }, 3067 | "node_modules/wrappy": { 3068 | "version": "1.0.2", 3069 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 3070 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 3071 | "license": "ISC" 3072 | }, 3073 | "node_modules/ws": { 3074 | "version": "8.18.2", 3075 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz", 3076 | "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==", 3077 | "license": "MIT", 3078 | "engines": { 3079 | "node": ">=10.0.0" 3080 | }, 3081 | "peerDependencies": { 3082 | "bufferutil": "^4.0.1", 3083 | "utf-8-validate": ">=5.0.2" 3084 | }, 3085 | "peerDependenciesMeta": { 3086 | "bufferutil": { 3087 | "optional": true 3088 | }, 3089 | "utf-8-validate": { 3090 | "optional": true 3091 | } 3092 | } 3093 | }, 3094 | "node_modules/y18n": { 3095 | "version": "5.0.8", 3096 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 3097 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 3098 | "engines": { 3099 | "node": ">=10" 3100 | } 3101 | }, 3102 | "node_modules/yaml": { 3103 | "version": "2.8.0", 3104 | "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", 3105 | "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", 3106 | "dev": true, 3107 | "license": "ISC", 3108 | "bin": { 3109 | "yaml": "bin.mjs" 3110 | }, 3111 | "engines": { 3112 | "node": ">= 14.6" 3113 | } 3114 | }, 3115 | "node_modules/yargs": { 3116 | "version": "17.7.2", 3117 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", 3118 | "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", 3119 | "dependencies": { 3120 | "cliui": "^8.0.1", 3121 | "escalade": "^3.1.1", 3122 | "get-caller-file": "^2.0.5", 3123 | "require-directory": "^2.1.1", 3124 | "string-width": "^4.2.3", 3125 | "y18n": "^5.0.5", 3126 | "yargs-parser": "^21.1.1" 3127 | }, 3128 | "engines": { 3129 | "node": ">=12" 3130 | } 3131 | }, 3132 | "node_modules/yargs-parser": { 3133 | "version": "21.1.1", 3134 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", 3135 | "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", 3136 | "engines": { 3137 | "node": ">=12" 3138 | } 3139 | }, 3140 | "node_modules/yn": { 3141 | "version": "3.1.1", 3142 | "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", 3143 | "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", 3144 | "dev": true, 3145 | "engines": { 3146 | "node": ">=6" 3147 | } 3148 | }, 3149 | "node_modules/zod": { 3150 | "version": "3.24.4", 3151 | "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz", 3152 | "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==", 3153 | "license": "MIT", 3154 | "funding": { 3155 | "url": "https://github.com/sponsors/colinhacks" 3156 | } 3157 | }, 3158 | "node_modules/zod-to-json-schema": { 3159 | "version": "3.24.1", 3160 | "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.1.tgz", 3161 | "integrity": "sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w==", 3162 | "license": "ISC", 3163 | "peerDependencies": { 3164 | "zod": "^3.24.1" 3165 | } 3166 | } 3167 | } 3168 | } 3169 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "supergateway", 3 | "version": "3.1.0", 4 | "description": "Run MCP stdio servers over SSE, Streamable HTTP or visa versa", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/supercorp-ai/supergateway.git" 8 | }, 9 | "keywords": [ 10 | "mcp", 11 | "stdio", 12 | "sse", 13 | "gateway", 14 | "proxy", 15 | "bridge" 16 | ], 17 | "type": "module", 18 | "bin": { 19 | "supergateway": "dist/index.js" 20 | }, 21 | "scripts": { 22 | "build": "tsc -p tsconfig.build.json", 23 | "start": "node dist/index.js", 24 | "format": "prettier --write 'src/**/*.ts' '*.json' '.prettierrc'", 25 | "format:check": "prettier --check 'src/**/*.ts' '*.json' '.prettierrc'", 26 | "test": "node --experimental-loader ts-node/esm --experimental-test-module-mocks --test 'tests/**/*.test.ts'", 27 | "prepare": "husky" 28 | }, 29 | "lint-staged": { 30 | "**/*": "prettier --write --ignore-unknown" 31 | }, 32 | "dependencies": { 33 | "@modelcontextprotocol/sdk": "^1.11.3", 34 | "body-parser": "^1.20.3", 35 | "cors": "^2.8.5", 36 | "express": "^4.21.2", 37 | "uuid": "^11.1.0", 38 | "ws": "^8.18.2", 39 | "yargs": "^17.7.2", 40 | "zod": "^3.24.4" 41 | }, 42 | "devDependencies": { 43 | "@types/body-parser": "^1.19.5", 44 | "prev-modelcontextprotocol-sdk": "npm:@modelcontextprotocol/sdk@1.4.0", 45 | "@types/cors": "^2.8.18", 46 | "@types/express": "^5.0.2", 47 | "@types/node": "^22.15.18", 48 | "@types/ws": "^8.18.1", 49 | "@types/yargs": "^17.0.33", 50 | "husky": "^9.1.7", 51 | "lint-staged": "^16.0.0", 52 | "prettier": "^3.5.3", 53 | "ts-node": "^10.9.2", 54 | "tsx": "^4.19.4", 55 | "typescript": "^5.8.3" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/gateways/sseToStdio.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '@modelcontextprotocol/sdk/client/index.js' 2 | import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js' 3 | import { Server } from '@modelcontextprotocol/sdk/server/index.js' 4 | import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js' 5 | import type { 6 | JSONRPCMessage, 7 | JSONRPCRequest, 8 | ClientCapabilities, 9 | Implementation, 10 | } from '@modelcontextprotocol/sdk/types.js' 11 | import { z } from 'zod' 12 | import { getVersion } from '../lib/getVersion.js' 13 | import { Logger } from '../types.js' 14 | import { onSignals } from '../lib/onSignals.js' 15 | 16 | export interface SseToStdioArgs { 17 | sseUrl: string 18 | logger: Logger 19 | headers: Record 20 | } 21 | 22 | let sseClient: Client | undefined 23 | 24 | const newInitializeSseClient = ({ message }: { message: JSONRPCRequest }) => { 25 | const clientInfo = message.params?.clientInfo as Implementation | undefined 26 | const clientCapabilities = message.params?.capabilities as 27 | | ClientCapabilities 28 | | undefined 29 | 30 | return new Client( 31 | { 32 | name: clientInfo?.name ?? 'supergateway', 33 | version: clientInfo?.version ?? getVersion(), 34 | }, 35 | { 36 | capabilities: clientCapabilities ?? {}, 37 | }, 38 | ) 39 | } 40 | 41 | const newFallbackSseClient = async ({ 42 | sseTransport, 43 | }: { 44 | sseTransport: SSEClientTransport 45 | }) => { 46 | const fallbackSseClient = new Client( 47 | { 48 | name: 'supergateway', 49 | version: getVersion(), 50 | }, 51 | { 52 | capabilities: {}, 53 | }, 54 | ) 55 | 56 | await fallbackSseClient.connect(sseTransport) 57 | return fallbackSseClient 58 | } 59 | 60 | export async function sseToStdio(args: SseToStdioArgs) { 61 | const { sseUrl, logger, headers } = args 62 | 63 | logger.info(` - sse: ${sseUrl}`) 64 | logger.info( 65 | ` - Headers: ${Object.keys(headers).length ? JSON.stringify(headers) : '(none)'}`, 66 | ) 67 | logger.info('Connecting to SSE...') 68 | 69 | onSignals({ logger }) 70 | 71 | const sseTransport = new SSEClientTransport(new URL(sseUrl), { 72 | eventSourceInit: { 73 | fetch: (...props: Parameters) => { 74 | const [url, init = {}] = props 75 | return fetch(url, { ...init, headers: { ...init.headers, ...headers } }) 76 | }, 77 | }, 78 | requestInit: { 79 | headers, 80 | }, 81 | }) 82 | 83 | sseTransport.onerror = (err) => { 84 | logger.error('SSE error:', err) 85 | } 86 | 87 | sseTransport.onclose = () => { 88 | logger.error('SSE connection closed') 89 | process.exit(1) 90 | } 91 | 92 | const stdioServer = new Server( 93 | { 94 | name: 'supergateway', 95 | version: getVersion(), 96 | }, 97 | { 98 | capabilities: {}, 99 | }, 100 | ) 101 | 102 | const stdioTransport = new StdioServerTransport() 103 | await stdioServer.connect(stdioTransport) 104 | 105 | const wrapResponse = (req: JSONRPCRequest, payload: object) => ({ 106 | jsonrpc: req.jsonrpc || '2.0', 107 | id: req.id, 108 | ...payload, 109 | }) 110 | 111 | stdioServer.transport!.onmessage = async (message: JSONRPCMessage) => { 112 | const isRequest = 'method' in message && 'id' in message 113 | if (isRequest) { 114 | logger.info('Stdio → SSE:', message) 115 | const req = message as JSONRPCRequest 116 | let result 117 | 118 | try { 119 | if (!sseClient) { 120 | if (message.method === 'initialize') { 121 | sseClient = newInitializeSseClient({ 122 | message, 123 | }) 124 | 125 | const originalRequest = sseClient.request 126 | 127 | sseClient.request = async function (requestMessage, ...restArgs) { 128 | // pass protocol version from original client 129 | if ( 130 | requestMessage.method === 'initialize' && 131 | message.params?.protocolVersion && 132 | requestMessage.params?.protocolVersion 133 | ) { 134 | requestMessage.params.protocolVersion = 135 | message.params.protocolVersion 136 | } 137 | 138 | result = await originalRequest.apply(this, [ 139 | requestMessage, 140 | ...restArgs, 141 | ]) 142 | 143 | return result 144 | } 145 | 146 | await sseClient.connect(sseTransport) 147 | sseClient.request = originalRequest 148 | } else { 149 | logger.info('SSE client not initialized, creating fallback client') 150 | sseClient = await newFallbackSseClient({ sseTransport }) 151 | } 152 | 153 | logger.info('SSE connected') 154 | } else { 155 | result = await sseClient.request(req, z.any()) 156 | } 157 | } catch (err) { 158 | logger.error('Request error:', err) 159 | const errorCode = 160 | err && typeof err === 'object' && 'code' in err 161 | ? (err as any).code 162 | : -32000 163 | let errorMsg = 164 | err && typeof err === 'object' && 'message' in err 165 | ? (err as any).message 166 | : 'Internal error' 167 | const prefix = `MCP error ${errorCode}:` 168 | if (errorMsg.startsWith(prefix)) { 169 | errorMsg = errorMsg.slice(prefix.length).trim() 170 | } 171 | const errorResp = wrapResponse(req, { 172 | error: { 173 | code: errorCode, 174 | message: errorMsg, 175 | }, 176 | }) 177 | process.stdout.write(JSON.stringify(errorResp) + '\n') 178 | return 179 | } 180 | const response = wrapResponse( 181 | req, 182 | result.hasOwnProperty('error') 183 | ? { error: { ...result.error } } 184 | : { result: { ...result } }, 185 | ) 186 | logger.info('Response:', response) 187 | process.stdout.write(JSON.stringify(response) + '\n') 188 | } else { 189 | logger.info('SSE → Stdio:', message) 190 | process.stdout.write(JSON.stringify(message) + '\n') 191 | } 192 | } 193 | 194 | logger.info('Stdio server listening') 195 | } 196 | -------------------------------------------------------------------------------- /src/gateways/stdioToSse.ts: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import bodyParser from 'body-parser' 3 | import cors, { type CorsOptions } from 'cors' 4 | import { spawn, ChildProcessWithoutNullStreams } from 'child_process' 5 | import { Server } from '@modelcontextprotocol/sdk/server/index.js' 6 | import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js' 7 | import { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js' 8 | import { Logger } from '../types.js' 9 | import { getVersion } from '../lib/getVersion.js' 10 | import { onSignals } from '../lib/onSignals.js' 11 | import { serializeCorsOrigin } from '../lib/serializeCorsOrigin.js' 12 | 13 | export interface StdioToSseArgs { 14 | stdioCmd: string 15 | port: number 16 | baseUrl: string 17 | ssePath: string 18 | messagePath: string 19 | logger: Logger 20 | corsOrigin: CorsOptions['origin'] 21 | healthEndpoints: string[] 22 | headers: Record 23 | } 24 | 25 | const setResponseHeaders = ({ 26 | res, 27 | headers, 28 | }: { 29 | res: express.Response 30 | headers: Record 31 | }) => 32 | Object.entries(headers).forEach(([key, value]) => { 33 | res.setHeader(key, value) 34 | }) 35 | 36 | export async function stdioToSse(args: StdioToSseArgs) { 37 | const { 38 | stdioCmd, 39 | port, 40 | baseUrl, 41 | ssePath, 42 | messagePath, 43 | logger, 44 | corsOrigin, 45 | healthEndpoints, 46 | headers, 47 | } = args 48 | 49 | logger.info( 50 | ` - Headers: ${Object(headers).length ? JSON.stringify(headers) : '(none)'}`, 51 | ) 52 | logger.info(` - port: ${port}`) 53 | logger.info(` - stdio: ${stdioCmd}`) 54 | if (baseUrl) { 55 | logger.info(` - baseUrl: ${baseUrl}`) 56 | } 57 | logger.info(` - ssePath: ${ssePath}`) 58 | logger.info(` - messagePath: ${messagePath}`) 59 | 60 | logger.info( 61 | ` - CORS: ${corsOrigin ? `enabled (${serializeCorsOrigin({ corsOrigin })})` : 'disabled'}`, 62 | ) 63 | logger.info( 64 | ` - Health endpoints: ${healthEndpoints.length ? healthEndpoints.join(', ') : '(none)'}`, 65 | ) 66 | 67 | onSignals({ logger }) 68 | 69 | const child: ChildProcessWithoutNullStreams = spawn(stdioCmd, { shell: true }) 70 | child.on('exit', (code, signal) => { 71 | logger.error(`Child exited: code=${code}, signal=${signal}`) 72 | process.exit(code ?? 1) 73 | }) 74 | 75 | const server = new Server( 76 | { name: 'supergateway', version: getVersion() }, 77 | { capabilities: {} }, 78 | ) 79 | 80 | const sessions: Record< 81 | string, 82 | { transport: SSEServerTransport; response: express.Response } 83 | > = {} 84 | 85 | const app = express() 86 | 87 | if (corsOrigin) { 88 | app.use(cors({ origin: corsOrigin })) 89 | } 90 | 91 | app.use((req, res, next) => { 92 | if (req.path === messagePath) return next() 93 | return bodyParser.json()(req, res, next) 94 | }) 95 | 96 | for (const ep of healthEndpoints) { 97 | app.get(ep, (_req, res) => { 98 | setResponseHeaders({ 99 | res, 100 | headers, 101 | }) 102 | res.send('ok') 103 | }) 104 | } 105 | 106 | app.get(ssePath, async (req, res) => { 107 | logger.info(`New SSE connection from ${req.ip}`) 108 | 109 | setResponseHeaders({ 110 | res, 111 | headers, 112 | }) 113 | 114 | const sseTransport = new SSEServerTransport(`${baseUrl}${messagePath}`, res) 115 | await server.connect(sseTransport) 116 | 117 | const sessionId = sseTransport.sessionId 118 | if (sessionId) { 119 | sessions[sessionId] = { transport: sseTransport, response: res } 120 | } 121 | 122 | sseTransport.onmessage = (msg: JSONRPCMessage) => { 123 | logger.info(`SSE → Child (session ${sessionId}): ${JSON.stringify(msg)}`) 124 | child.stdin.write(JSON.stringify(msg) + '\n') 125 | } 126 | 127 | sseTransport.onclose = () => { 128 | logger.info(`SSE connection closed (session ${sessionId})`) 129 | delete sessions[sessionId] 130 | } 131 | 132 | sseTransport.onerror = (err) => { 133 | logger.error(`SSE error (session ${sessionId}):`, err) 134 | delete sessions[sessionId] 135 | } 136 | 137 | req.on('close', () => { 138 | logger.info(`Client disconnected (session ${sessionId})`) 139 | delete sessions[sessionId] 140 | }) 141 | }) 142 | 143 | // @ts-ignore 144 | app.post(messagePath, async (req, res) => { 145 | const sessionId = req.query.sessionId as string 146 | 147 | setResponseHeaders({ 148 | res, 149 | headers, 150 | }) 151 | 152 | if (!sessionId) { 153 | return res.status(400).send('Missing sessionId parameter') 154 | } 155 | 156 | const session = sessions[sessionId] 157 | if (session?.transport?.handlePostMessage) { 158 | logger.info(`POST to SSE transport (session ${sessionId})`) 159 | await session.transport.handlePostMessage(req, res) 160 | } else { 161 | res.status(503).send(`No active SSE connection for session ${sessionId}`) 162 | } 163 | }) 164 | 165 | app.listen(port, () => { 166 | logger.info(`Listening on port ${port}`) 167 | logger.info(`SSE endpoint: http://localhost:${port}${ssePath}`) 168 | logger.info(`POST messages: http://localhost:${port}${messagePath}`) 169 | }) 170 | 171 | let buffer = '' 172 | child.stdout.on('data', (chunk: Buffer) => { 173 | buffer += chunk.toString('utf8') 174 | const lines = buffer.split(/\r?\n/) 175 | buffer = lines.pop() ?? '' 176 | lines.forEach((line) => { 177 | if (!line.trim()) return 178 | try { 179 | const jsonMsg = JSON.parse(line) 180 | logger.info('Child → SSE:', jsonMsg) 181 | for (const [sid, session] of Object.entries(sessions)) { 182 | try { 183 | session.transport.send(jsonMsg) 184 | } catch (err) { 185 | logger.error(`Failed to send to session ${sid}:`, err) 186 | delete sessions[sid] 187 | } 188 | } 189 | } catch { 190 | logger.error(`Child non-JSON: ${line}`) 191 | } 192 | }) 193 | }) 194 | 195 | child.stderr.on('data', (chunk: Buffer) => { 196 | logger.error(`Child stderr: ${chunk.toString('utf8')}`) 197 | }) 198 | } 199 | -------------------------------------------------------------------------------- /src/gateways/stdioToWs.ts: -------------------------------------------------------------------------------- 1 | import express from 'express' 2 | import cors, { type CorsOptions } from 'cors' 3 | import { createServer } from 'http' 4 | import { spawn, ChildProcessWithoutNullStreams } from 'child_process' 5 | import { Server } from '@modelcontextprotocol/sdk/server/index.js' 6 | import { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js' 7 | import { Logger } from '../types.js' 8 | import { getVersion } from '../lib/getVersion.js' 9 | import { WebSocketServerTransport } from '../server/websocket.js' 10 | import { onSignals } from '../lib/onSignals.js' 11 | import { serializeCorsOrigin } from '../lib/serializeCorsOrigin.js' 12 | 13 | export interface StdioToWsArgs { 14 | stdioCmd: string 15 | port: number 16 | messagePath: string 17 | logger: Logger 18 | corsOrigin: CorsOptions['origin'] 19 | healthEndpoints: string[] 20 | } 21 | 22 | export async function stdioToWs(args: StdioToWsArgs) { 23 | const { stdioCmd, port, messagePath, logger, healthEndpoints, corsOrigin } = 24 | args 25 | logger.info(` - port: ${port}`) 26 | logger.info(` - stdio: ${stdioCmd}`) 27 | logger.info(` - messagePath: ${messagePath}`) 28 | logger.info( 29 | ` - CORS: ${corsOrigin ? `enabled (${serializeCorsOrigin({ corsOrigin })})` : 'disabled'}`, 30 | ) 31 | logger.info( 32 | ` - Health endpoints: ${healthEndpoints.length ? healthEndpoints.join(', ') : '(none)'}`, 33 | ) 34 | 35 | let wsTransport: WebSocketServerTransport | null = null 36 | let child: ChildProcessWithoutNullStreams | null = null 37 | let isReady = false 38 | 39 | const cleanup = () => { 40 | if (wsTransport) { 41 | wsTransport.close().catch((err) => { 42 | logger.error(`Error stopping WebSocket server: ${err.message}`) 43 | }) 44 | } 45 | if (child) { 46 | child.kill() 47 | } 48 | } 49 | 50 | onSignals({ 51 | logger, 52 | cleanup, 53 | }) 54 | 55 | try { 56 | child = spawn(stdioCmd, { shell: true }) 57 | child.on('exit', (code, signal) => { 58 | logger.error(`Child exited: code=${code}, signal=${signal}`) 59 | cleanup() 60 | process.exit(code ?? 1) 61 | }) 62 | 63 | const server = new Server( 64 | { name: 'supergateway', version: getVersion() }, 65 | { capabilities: {} }, 66 | ) 67 | 68 | // Handle child process output 69 | let buffer = '' 70 | child.stdout.on('data', (chunk: Buffer) => { 71 | buffer += chunk.toString('utf8') 72 | const lines = buffer.split(/\r?\n/) 73 | buffer = lines.pop() ?? '' 74 | lines.forEach((line) => { 75 | if (!line.trim()) return 76 | try { 77 | const jsonMsg = JSON.parse(line) 78 | logger.info(`Child → WebSocket: ${JSON.stringify(jsonMsg)}`) 79 | // Broadcast to all connected clients 80 | wsTransport?.send(jsonMsg, jsonMsg.id).catch((err) => { 81 | logger.error('Failed to broadcast message:', err) 82 | }) 83 | } catch { 84 | logger.error(`Child non-JSON: ${line}`) 85 | } 86 | }) 87 | }) 88 | 89 | child.stderr.on('data', (chunk: Buffer) => { 90 | logger.info(`Child stderr: ${chunk.toString('utf8')}`) 91 | }) 92 | 93 | const app = express() 94 | 95 | if (corsOrigin) { 96 | app.use(cors({ origin: corsOrigin })) 97 | } 98 | 99 | for (const ep of healthEndpoints) { 100 | app.get(ep, (_req, res) => { 101 | if (child?.killed) { 102 | res.status(500).send('Child process has been killed') 103 | } 104 | 105 | if (!isReady) { 106 | res.status(500).send('Server is not ready') 107 | } 108 | 109 | res.send('ok') 110 | }) 111 | } 112 | 113 | const httpServer = createServer(app) 114 | 115 | wsTransport = new WebSocketServerTransport({ 116 | path: messagePath, 117 | server: httpServer, 118 | }) 119 | 120 | await server.connect(wsTransport) 121 | 122 | wsTransport.onmessage = (msg: JSONRPCMessage) => { 123 | const line = JSON.stringify(msg) 124 | logger.info(`WebSocket → Child: ${line}`) 125 | child!.stdin.write(line + '\n') 126 | } 127 | 128 | wsTransport.onconnection = (clientId: string) => { 129 | logger.info(`New WebSocket connection: ${clientId}`) 130 | } 131 | 132 | wsTransport.ondisconnection = (clientId: string) => { 133 | logger.info(`WebSocket connection closed: ${clientId}`) 134 | } 135 | 136 | wsTransport.onerror = (err: Error) => { 137 | logger.error(`WebSocket error: ${err.message}`) 138 | } 139 | 140 | isReady = true 141 | 142 | httpServer.listen(port, () => { 143 | logger.info(`Listening on port ${port}`) 144 | logger.info(`WebSocket endpoint: ws://localhost:${port}${messagePath}`) 145 | }) 146 | } catch (err: any) { 147 | logger.error(`Failed to start: ${err.message}`) 148 | cleanup() 149 | process.exit(1) 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/gateways/streamableHttpToStdio.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '@modelcontextprotocol/sdk/client/index.js' 2 | import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js' 3 | import { Server } from '@modelcontextprotocol/sdk/server/index.js' 4 | import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js' 5 | import type { 6 | JSONRPCMessage, 7 | JSONRPCRequest, 8 | ClientCapabilities, 9 | Implementation, 10 | } from '@modelcontextprotocol/sdk/types.js' 11 | import { InitializeRequestSchema } from '@modelcontextprotocol/sdk/types.js' 12 | import { z } from 'zod' 13 | import { getVersion } from '../lib/getVersion.js' 14 | import { Logger } from '../types.js' 15 | import { onSignals } from '../lib/onSignals.js' 16 | 17 | export interface StreamableHttpToStdioArgs { 18 | streamableHttpUrl: string 19 | logger: Logger 20 | headers: Record 21 | } 22 | 23 | let mcpClient: Client | undefined 24 | 25 | const newInitializeMcpClient = ({ message }: { message: JSONRPCRequest }) => { 26 | const clientInfo = message.params?.clientInfo as Implementation | undefined 27 | const clientCapabilities = message.params?.capabilities as 28 | | ClientCapabilities 29 | | undefined 30 | 31 | return new Client( 32 | { 33 | name: clientInfo?.name ?? 'supergateway', 34 | version: clientInfo?.version ?? getVersion(), 35 | }, 36 | { 37 | capabilities: clientCapabilities ?? {}, 38 | }, 39 | ) 40 | } 41 | 42 | const newFallbackMcpClient = async ({ 43 | mcpTransport, 44 | }: { 45 | mcpTransport: StreamableHTTPClientTransport 46 | }) => { 47 | const fallbackMcpClient = new Client( 48 | { 49 | name: 'supergateway', 50 | version: getVersion(), 51 | }, 52 | { 53 | capabilities: {}, 54 | }, 55 | ) 56 | 57 | await fallbackMcpClient.connect(mcpTransport) 58 | return fallbackMcpClient 59 | } 60 | 61 | export async function streamableHttpToStdio(args: StreamableHttpToStdioArgs) { 62 | const { streamableHttpUrl, logger, headers } = args 63 | 64 | logger.info(` - streamableHttp: ${streamableHttpUrl}`) 65 | logger.info( 66 | ` - Headers: ${Object.keys(headers).length ? JSON.stringify(headers) : '(none)'}`, 67 | ) 68 | logger.info('Connecting to Streamable HTTP...') 69 | 70 | onSignals({ logger }) 71 | 72 | const mcpTransport = new StreamableHTTPClientTransport( 73 | new URL(streamableHttpUrl), 74 | { 75 | requestInit: { 76 | headers, 77 | }, 78 | }, 79 | ) 80 | 81 | mcpTransport.onerror = (err) => { 82 | logger.error('Streamable HTTP error:', err) 83 | } 84 | 85 | mcpTransport.onclose = () => { 86 | logger.error('Streamable HTTP connection closed') 87 | process.exit(1) 88 | } 89 | 90 | const stdioServer = new Server( 91 | { 92 | name: 'supergateway', 93 | version: getVersion(), 94 | }, 95 | { 96 | capabilities: {}, 97 | }, 98 | ) 99 | 100 | const stdioTransport = new StdioServerTransport() 101 | await stdioServer.connect(stdioTransport) 102 | 103 | const wrapResponse = (req: JSONRPCRequest, payload: object) => ({ 104 | jsonrpc: req.jsonrpc || '2.0', 105 | id: req.id, 106 | ...payload, 107 | }) 108 | 109 | stdioServer.transport!.onmessage = async (message: JSONRPCMessage) => { 110 | const isRequest = 'method' in message && 'id' in message 111 | if (isRequest) { 112 | logger.info('Stdio → Streamable HTTP:', message) 113 | const req = message as JSONRPCRequest 114 | let result 115 | 116 | try { 117 | if (!mcpClient) { 118 | if (message.method === 'initialize') { 119 | mcpClient = newInitializeMcpClient({ 120 | message, 121 | }) 122 | 123 | const originalRequest = mcpClient.request 124 | 125 | mcpClient.request = async function ( 126 | possibleInitRequestMessage, 127 | ...restArgs 128 | ) { 129 | if ( 130 | InitializeRequestSchema.safeParse(possibleInitRequestMessage) 131 | .success && 132 | message.params?.protocolVersion 133 | ) { 134 | // respect the protocol version from the stdio client's init request 135 | possibleInitRequestMessage.params!.protocolVersion = 136 | message.params.protocolVersion 137 | } 138 | result = await originalRequest.apply(this, [ 139 | possibleInitRequestMessage, 140 | ...restArgs, 141 | ]) 142 | return result 143 | } 144 | 145 | await mcpClient.connect(mcpTransport) 146 | mcpClient.request = originalRequest 147 | } else { 148 | logger.info( 149 | 'Streamable HTTP client not initialized, creating fallback client', 150 | ) 151 | mcpClient = await newFallbackMcpClient({ mcpTransport }) 152 | } 153 | 154 | logger.info('Streamable HTTP connected') 155 | } else { 156 | result = await mcpClient.request(req, z.any()) 157 | } 158 | } catch (err) { 159 | logger.error('Request error:', err) 160 | const errorCode = 161 | err && typeof err === 'object' && 'code' in err 162 | ? (err as any).code 163 | : -32000 164 | let errorMsg = 165 | err && typeof err === 'object' && 'message' in err 166 | ? (err as any).message 167 | : 'Internal error' 168 | const prefix = `MCP error ${errorCode}:` 169 | if (errorMsg.startsWith(prefix)) { 170 | errorMsg = errorMsg.slice(prefix.length).trim() 171 | } 172 | const errorResp = wrapResponse(req, { 173 | error: { 174 | code: errorCode, 175 | message: errorMsg, 176 | }, 177 | }) 178 | process.stdout.write(JSON.stringify(errorResp) + '\n') 179 | return 180 | } 181 | const response = wrapResponse( 182 | req, 183 | result.hasOwnProperty('error') 184 | ? { error: { ...result.error } } 185 | : { result: { ...result } }, 186 | ) 187 | logger.info('Response:', response) 188 | process.stdout.write(JSON.stringify(response) + '\n') 189 | } else { 190 | logger.info('Streamable HTTP → Stdio:', message) 191 | process.stdout.write(JSON.stringify(message) + '\n') 192 | } 193 | } 194 | 195 | logger.info('Stdio server listening') 196 | } 197 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /** 3 | * index.ts 4 | * 5 | * Run MCP stdio servers over SSE, convert between stdio, SSE, WS. 6 | * 7 | * Usage: 8 | * # stdio→SSE 9 | * npx -y supergateway --stdio "npx -y @modelcontextprotocol/server-filesystem /" \ 10 | * --port 8000 --baseUrl http://localhost:8000 --ssePath /sse --messagePath /message 11 | * 12 | * # SSE→stdio 13 | * npx -y supergateway --sse "https://mcp-server-ab71a6b2-cd55-49d0-adba-562bc85956e3.supermachine.app" 14 | * 15 | * # stdio→WS 16 | * npx -y supergateway --stdio "npx -y @modelcontextprotocol/server-filesystem /" --outputTransport ws 17 | * 18 | * # Streamable HTTP→stdio 19 | * npx -y supergateway --streamableHttp "https://mcp-server.example.com/mcp" 20 | */ 21 | 22 | import yargs from 'yargs' 23 | import { hideBin } from 'yargs/helpers' 24 | import { stdioToSse } from './gateways/stdioToSse.js' 25 | import { sseToStdio } from './gateways/sseToStdio.js' 26 | import { stdioToWs } from './gateways/stdioToWs.js' 27 | import { streamableHttpToStdio } from './gateways/streamableHttpToStdio.js' 28 | import { headers } from './lib/headers.js' 29 | import { corsOrigin } from './lib/corsOrigin.js' 30 | import { getLogger } from './lib/getLogger.js' 31 | 32 | async function main() { 33 | const argv = yargs(hideBin(process.argv)) 34 | .option('stdio', { 35 | type: 'string', 36 | description: 'Command to run an MCP server over Stdio', 37 | }) 38 | .option('sse', { 39 | type: 'string', 40 | description: 'SSE URL to connect to', 41 | }) 42 | .option('streamableHttp', { 43 | type: 'string', 44 | description: 'Streamable HTTP URL to connect to', 45 | }) 46 | .option('outputTransport', { 47 | type: 'string', 48 | choices: ['stdio', 'sse', 'ws'], 49 | default: () => { 50 | const args = hideBin(process.argv) 51 | 52 | if (args.includes('--stdio')) return 'sse' 53 | if (args.includes('--sse')) return 'stdio' 54 | if (args.includes('--streamableHttp')) return 'stdio' 55 | 56 | return undefined 57 | }, 58 | description: 59 | 'Transport for output. Default is "sse" when using --stdio and "stdio" when using --sse or --streamableHttp.', 60 | }) 61 | .option('port', { 62 | type: 'number', 63 | default: 8000, 64 | description: '(stdio→SSE, stdio→WS) Port for output MCP server', 65 | }) 66 | .option('baseUrl', { 67 | type: 'string', 68 | default: '', 69 | description: '(stdio→SSE) Base URL for output MCP server', 70 | }) 71 | .option('ssePath', { 72 | type: 'string', 73 | default: '/sse', 74 | description: '(stdio→SSE) Path for SSE subscriptions', 75 | }) 76 | .option('messagePath', { 77 | type: 'string', 78 | default: '/message', 79 | description: '(stdio→SSE, stdio→WS) Path for messages', 80 | }) 81 | .option('logLevel', { 82 | choices: ['debug', 'info', 'none'] as const, 83 | default: 'info', 84 | description: 'Logging level', 85 | }) 86 | .option('cors', { 87 | type: 'array', 88 | description: 89 | 'Enable CORS. Use --cors with no values to allow all origins, or supply one or more allowed origins (e.g. --cors "http://example.com" or --cors "/example\\.com$/" for regex matching).', 90 | }) 91 | .option('healthEndpoint', { 92 | type: 'array', 93 | default: [], 94 | description: 95 | 'One or more endpoints returning "ok", e.g. --healthEndpoint /healthz --healthEndpoint /readyz', 96 | }) 97 | .option('header', { 98 | type: 'array', 99 | default: [], 100 | description: 101 | 'Headers to be added to the request headers, e.g. --header "x-user-id: 123"', 102 | }) 103 | .option('oauth2Bearer', { 104 | type: 'string', 105 | description: 106 | 'Authorization header to be added, e.g. --oauth2Bearer "some-access-token" adds "Authorization: Bearer some-access-token"', 107 | }) 108 | .help() 109 | .parseSync() 110 | 111 | const hasStdio = Boolean(argv.stdio) 112 | const hasSse = Boolean(argv.sse) 113 | const hasStreamableHttp = Boolean(argv.streamableHttp) 114 | 115 | const activeCount = [hasStdio, hasSse, hasStreamableHttp].filter( 116 | Boolean, 117 | ).length 118 | 119 | const logger = getLogger({ 120 | logLevel: argv.logLevel, 121 | outputTransport: argv.outputTransport as string, 122 | }) 123 | 124 | if (activeCount === 0) { 125 | logger.error( 126 | 'Error: You must specify one of --stdio, --sse, or --streamableHttp', 127 | ) 128 | process.exit(1) 129 | } else if (activeCount > 1) { 130 | logger.error( 131 | 'Error: Specify only one of --stdio, --sse, or --streamableHttp, not multiple', 132 | ) 133 | process.exit(1) 134 | } 135 | 136 | logger.info('Starting...') 137 | logger.info( 138 | 'Supergateway is supported by Supermachine (hosted MCPs) - https://supermachine.ai', 139 | ) 140 | logger.info(` - outputTransport: ${argv.outputTransport}`) 141 | 142 | try { 143 | if (hasStdio) { 144 | if (argv.outputTransport === 'sse') { 145 | await stdioToSse({ 146 | stdioCmd: argv.stdio!, 147 | port: argv.port, 148 | baseUrl: argv.baseUrl, 149 | ssePath: argv.ssePath, 150 | messagePath: argv.messagePath, 151 | logger, 152 | corsOrigin: corsOrigin({ argv }), 153 | healthEndpoints: argv.healthEndpoint as string[], 154 | headers: headers({ 155 | argv, 156 | logger, 157 | }), 158 | }) 159 | } else if (argv.outputTransport === 'ws') { 160 | await stdioToWs({ 161 | stdioCmd: argv.stdio!, 162 | port: argv.port, 163 | messagePath: argv.messagePath, 164 | logger, 165 | corsOrigin: corsOrigin({ argv }), 166 | healthEndpoints: argv.healthEndpoint as string[], 167 | }) 168 | } else { 169 | logger.error(`Error: stdio→${argv.outputTransport} not supported`) 170 | process.exit(1) 171 | } 172 | } else if (hasSse) { 173 | if (argv.outputTransport === 'stdio') { 174 | await sseToStdio({ 175 | sseUrl: argv.sse!, 176 | logger, 177 | headers: headers({ 178 | argv, 179 | logger, 180 | }), 181 | }) 182 | } else { 183 | logger.error(`Error: sse→${argv.outputTransport} not supported`) 184 | process.exit(1) 185 | } 186 | } else if (hasStreamableHttp) { 187 | if (argv.outputTransport === 'stdio') { 188 | await streamableHttpToStdio({ 189 | streamableHttpUrl: argv.streamableHttp!, 190 | logger, 191 | headers: headers({ 192 | argv, 193 | logger, 194 | }), 195 | }) 196 | } else { 197 | logger.error( 198 | `Error: streamableHttp→${argv.outputTransport} not supported`, 199 | ) 200 | process.exit(1) 201 | } 202 | } else { 203 | logger.error('Error: Invalid input transport') 204 | process.exit(1) 205 | } 206 | } catch (err) { 207 | logger.error('Fatal error:', err) 208 | process.exit(1) 209 | } 210 | } 211 | 212 | main() 213 | -------------------------------------------------------------------------------- /src/lib/corsOrigin.ts: -------------------------------------------------------------------------------- 1 | export const corsOrigin = ({ 2 | argv, 3 | }: { 4 | argv: { 5 | cors: (string | number)[] | undefined 6 | } 7 | }) => { 8 | if (!argv.cors) { 9 | return false 10 | } 11 | 12 | if (argv.cors.length === 0) { 13 | return '*' 14 | } 15 | 16 | const origins = argv.cors.map((item) => `${item}`) 17 | 18 | if (origins.includes('*')) return '*' 19 | 20 | return origins.map((origin) => { 21 | if (/^\/.*\/$/.test(origin)) { 22 | const pattern = origin.slice(1, -1) 23 | try { 24 | return new RegExp(pattern) 25 | } catch (error) { 26 | return origin 27 | } 28 | } 29 | return origin 30 | }) 31 | } 32 | -------------------------------------------------------------------------------- /src/lib/getLogger.ts: -------------------------------------------------------------------------------- 1 | import util from 'node:util' 2 | import { Logger } from '../types.js' 3 | 4 | const defaultFormatArgs = (args: any[]) => args 5 | 6 | const log = 7 | ( 8 | { 9 | formatArgs = defaultFormatArgs, 10 | }: { 11 | formatArgs?: typeof defaultFormatArgs 12 | } = { formatArgs: defaultFormatArgs }, 13 | ) => 14 | (...args: any[]) => 15 | console.log('[supergateway]', ...formatArgs(args)) 16 | 17 | const logStderr = 18 | ( 19 | { 20 | formatArgs = defaultFormatArgs, 21 | }: { 22 | formatArgs?: typeof defaultFormatArgs 23 | } = { formatArgs: defaultFormatArgs }, 24 | ) => 25 | (...args: any[]) => 26 | console.error('[supergateway]', ...formatArgs(args)) 27 | 28 | const noneLogger: Logger = { 29 | info: () => {}, 30 | error: () => {}, 31 | } 32 | 33 | const infoLogger: Logger = { 34 | info: log(), 35 | error: logStderr(), 36 | } 37 | 38 | const infoLoggerStdio: Logger = { 39 | info: logStderr(), 40 | error: logStderr(), 41 | } 42 | 43 | const debugFormatArgs = (args: any[]) => 44 | args.map((arg) => { 45 | if (typeof arg === 'object') { 46 | return util.inspect(arg, { 47 | depth: null, 48 | colors: process.stderr.isTTY, 49 | compact: false, 50 | }) 51 | } 52 | 53 | return arg 54 | }) 55 | 56 | const debugLogger: Logger = { 57 | info: log({ formatArgs: debugFormatArgs }), 58 | error: logStderr({ formatArgs: debugFormatArgs }), 59 | } 60 | 61 | const debugLoggerStdio: Logger = { 62 | info: logStderr({ formatArgs: debugFormatArgs }), 63 | error: logStderr({ formatArgs: debugFormatArgs }), 64 | } 65 | 66 | export const getLogger = ({ 67 | logLevel, 68 | outputTransport, 69 | }: { 70 | logLevel: string 71 | outputTransport: string 72 | }): Logger => { 73 | if (logLevel === 'none') { 74 | return noneLogger 75 | } 76 | 77 | if (logLevel === 'debug') { 78 | return outputTransport === 'stdio' ? debugLoggerStdio : debugLogger 79 | } 80 | 81 | // info logLevel 82 | return outputTransport === 'stdio' ? infoLoggerStdio : infoLogger 83 | } 84 | -------------------------------------------------------------------------------- /src/lib/getVersion.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'url' 2 | import { join, dirname } from 'path' 3 | import { readFileSync } from 'fs' 4 | 5 | const __filename = fileURLToPath(import.meta.url) 6 | const __dirname = dirname(__filename) 7 | 8 | export function getVersion(): string { 9 | try { 10 | const packageJsonPath = join(__dirname, '../../package.json') 11 | const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) 12 | return packageJson.version || '1.0.0' 13 | } catch (err) { 14 | console.error('[supergateway]', 'Unable to retrieve version:', err) 15 | return 'unknown' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/lib/headers.ts: -------------------------------------------------------------------------------- 1 | import { Logger } from '../types.js' 2 | 3 | const parseHeaders = ({ 4 | argvHeader, 5 | logger, 6 | }: { 7 | argvHeader: (string | number)[] 8 | logger: Logger 9 | }): Record => { 10 | return argvHeader.reduce>((acc, rawHeader) => { 11 | const header = `${rawHeader}` 12 | 13 | const colonIndex = header.indexOf(':') 14 | if (colonIndex === -1) { 15 | logger.error(`Invalid header format: ${header}, ignoring`) 16 | return acc 17 | } 18 | 19 | const key = header.slice(0, colonIndex).trim() 20 | const value = header.slice(colonIndex + 1).trim() 21 | 22 | if (!key || !value) { 23 | logger.error(`Invalid header format: ${header}, ignoring`) 24 | return acc 25 | } 26 | 27 | acc[key] = value 28 | return acc 29 | }, {}) 30 | } 31 | 32 | export const headers = ({ 33 | argv, 34 | logger, 35 | }: { 36 | argv: { 37 | header: (string | number)[] 38 | oauth2Bearer: string | undefined 39 | } 40 | logger: Logger 41 | }): Record => { 42 | const headers = parseHeaders({ 43 | argvHeader: argv.header, 44 | logger, 45 | }) 46 | 47 | if ('oauth2Bearer' in argv) { 48 | return { 49 | ...headers, 50 | Authorization: `Bearer ${argv.oauth2Bearer}`, 51 | } 52 | } 53 | 54 | return headers 55 | } 56 | -------------------------------------------------------------------------------- /src/lib/onSignals.ts: -------------------------------------------------------------------------------- 1 | import { Logger } from '../types.js' 2 | 3 | export interface OnSignalsOptions { 4 | logger: Logger 5 | cleanup?: () => void 6 | } 7 | 8 | /** 9 | * Sets up signal handlers for graceful shutdown. 10 | * 11 | * @param options Configuration options 12 | * @param options.logger Logger instance 13 | * @param options.cleanup Optional cleanup function to be called before exit 14 | */ 15 | export function onSignals(options: OnSignalsOptions): void { 16 | const { logger, cleanup } = options 17 | 18 | const handleSignal = (signal: string) => { 19 | logger.info(`Caught ${signal}. Exiting...`) 20 | if (cleanup) { 21 | cleanup() 22 | } 23 | process.exit(0) 24 | } 25 | 26 | process.on('SIGINT', () => handleSignal('SIGINT')) 27 | 28 | process.on('SIGTERM', () => handleSignal('SIGTERM')) 29 | 30 | process.on('SIGHUP', () => handleSignal('SIGHUP')) 31 | 32 | process.stdin.on('close', () => { 33 | logger.info('stdin closed. Exiting...') 34 | if (cleanup) { 35 | cleanup() 36 | } 37 | process.exit(0) 38 | }) 39 | } 40 | -------------------------------------------------------------------------------- /src/lib/serializeCorsOrigin.ts: -------------------------------------------------------------------------------- 1 | import type { CorsOptions } from 'cors' 2 | 3 | export const serializeCorsOrigin = ({ 4 | corsOrigin, 5 | }: { 6 | corsOrigin: CorsOptions['origin'] 7 | }) => 8 | JSON.stringify(corsOrigin, (_key, value) => { 9 | if (value instanceof RegExp) { 10 | return value.toString() 11 | } 12 | 13 | return value 14 | }) 15 | -------------------------------------------------------------------------------- /src/server/websocket.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Transport, 3 | TransportSendOptions, 4 | } from '@modelcontextprotocol/sdk/shared/transport.js' 5 | import { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js' 6 | import { v4 as uuidv4 } from 'uuid' 7 | import { WebSocket, WebSocketServer } from 'ws' 8 | import { Server } from 'http' 9 | 10 | export class WebSocketServerTransport implements Transport { 11 | private wss!: WebSocketServer 12 | private clients: Map = new Map() 13 | 14 | onclose?: () => void 15 | onerror?: (err: Error) => void 16 | private messageHandler?: (msg: JSONRPCMessage, clientId: string) => void 17 | onconnection?: (clientId: string) => void 18 | ondisconnection?: (clientId: string) => void 19 | 20 | set onmessage(handler: ((message: JSONRPCMessage) => void) | undefined) { 21 | this.messageHandler = handler 22 | ? (msg, clientId) => { 23 | // @ts-ignore 24 | if (msg.id === undefined) { 25 | console.log('Broadcast message:', msg) 26 | return handler(msg) 27 | } 28 | // @ts-ignore 29 | return handler({ 30 | ...msg, 31 | // @ts-ignore 32 | id: clientId + ':' + msg.id, 33 | }) 34 | } 35 | : undefined 36 | } 37 | 38 | constructor({ path, server }: { path: string; server: Server }) { 39 | this.wss = new WebSocketServer({ 40 | path, 41 | server, 42 | }) 43 | } 44 | 45 | async start(): Promise { 46 | this.wss.on('connection', (ws: WebSocket) => { 47 | const clientId = uuidv4() 48 | this.clients.set(clientId, ws) 49 | this.onconnection?.(clientId) 50 | 51 | ws.on('message', (data: Buffer) => { 52 | try { 53 | const msg = JSON.parse(data.toString()) 54 | this.messageHandler?.(msg, clientId) 55 | } catch (err) { 56 | this.onerror?.(new Error(`Failed to parse message: ${err}`)) 57 | } 58 | }) 59 | 60 | ws.on('close', () => { 61 | this.clients.delete(clientId) 62 | this.ondisconnection?.(clientId) 63 | }) 64 | 65 | ws.on('error', (err: Error) => { 66 | this.onerror?.(err) 67 | }) 68 | }) 69 | } 70 | 71 | async send( 72 | msg: JSONRPCMessage, 73 | options?: TransportSendOptions | string, 74 | ): Promise { 75 | // decide if they passed a raw clientId (legacy) or options object 76 | const clientId = typeof options === 'string' ? options : undefined 77 | 78 | // if your protocol mangles IDs to include clientId, strip it off 79 | const [cId, rawId] = clientId?.split(':') ?? [] 80 | if (rawId !== undefined) { 81 | // @ts-ignore 82 | msg.id = parseInt(rawId, 10) 83 | } 84 | 85 | const payload = JSON.stringify(msg) 86 | 87 | if (cId) { 88 | // send only to the one client 89 | const ws = this.clients.get(cId) 90 | if (ws?.readyState === WebSocket.OPEN) { 91 | ws.send(payload) 92 | } else { 93 | this.clients.delete(cId) 94 | this.ondisconnection?.(cId) 95 | } 96 | } else { 97 | // broadcast to everyone 98 | for (const [id, ws] of this.clients) { 99 | if (ws.readyState === WebSocket.OPEN) { 100 | ws.send(payload) 101 | } else { 102 | this.clients.delete(id) 103 | this.ondisconnection?.(id) 104 | } 105 | } 106 | } 107 | } 108 | 109 | async broadcast(msg: JSONRPCMessage): Promise { 110 | return this.send(msg) 111 | } 112 | 113 | async close(): Promise { 114 | return new Promise((resolve) => { 115 | this.wss.close(() => { 116 | this.clients.clear() 117 | resolve() 118 | }) 119 | }) 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | export interface Logger { 2 | info: (...args: any[]) => void 3 | error: (...args: any[]) => void 4 | } 5 | -------------------------------------------------------------------------------- /supergateway.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/supercorp-ai/supergateway/f49601663324310463757f45f8d35633ccc045ff/supergateway.png -------------------------------------------------------------------------------- /tests/baseUrl.test.ts: -------------------------------------------------------------------------------- 1 | import { test } from 'node:test' 2 | import assert from 'node:assert/strict' 3 | import { spawn, ChildProcess } from 'child_process' 4 | 5 | const PORT = 11000 6 | const BASE_URL = `http://0.0.0.0:${PORT}` 7 | const SSE_PATH = '/sse' 8 | const MESSAGE_PATH = '/message' 9 | 10 | let gatewayProc: ChildProcess 11 | 12 | test.before(() => { 13 | gatewayProc = spawn( 14 | 'npm', 15 | [ 16 | 'run', 17 | 'start', 18 | '--', 19 | '--stdio', 20 | 'npx -y @modelcontextprotocol/server-memory', 21 | '--outputTransport', 22 | 'sse', 23 | '--port', 24 | String(PORT), 25 | '--baseUrl', 26 | BASE_URL, 27 | '--ssePath', 28 | SSE_PATH, 29 | '--messagePath', 30 | MESSAGE_PATH, 31 | ], 32 | { stdio: 'inherit', shell: false }, 33 | ) 34 | }) 35 | 36 | test.after(() => { 37 | gatewayProc.kill('SIGINT') 38 | }) 39 | 40 | test('baseUrl should be passed correctly in endpoint event', async (t) => { 41 | const endpointSpy = t.mock.fn() 42 | const { EventSource } = await import('eventsource') 43 | class EventSourceSpy extends EventSource { 44 | constructor(url: string | URL, init?: EventSourceInit) { 45 | super(url as any, init) 46 | this.addEventListener('endpoint', endpointSpy) 47 | } 48 | close() { 49 | super.close() 50 | } 51 | } 52 | t.mock.module('eventsource', { 53 | defaultExport: EventSourceSpy, 54 | namedExports: { EventSource: EventSourceSpy }, 55 | }) 56 | 57 | const [{ Client }, { SSEClientTransport }] = await Promise.all([ 58 | import('@modelcontextprotocol/sdk/client/index.js'), 59 | import('@modelcontextprotocol/sdk/client/sse.js'), 60 | ]) 61 | 62 | const transport = new SSEClientTransport(new URL(SSE_PATH, BASE_URL)) 63 | const client = new Client({ name: 'endpoint-tester', version: '1.0.0' }) 64 | 65 | await new Promise((resolve) => { 66 | setTimeout(() => resolve(true), 3000) 67 | }) 68 | 69 | await client.connect(transport) 70 | await client.close() 71 | 72 | assert.strictEqual(endpointSpy.mock.callCount(), 1) 73 | 74 | const data: string = endpointSpy.mock.calls[0].arguments[0].data 75 | 76 | // should be this instead 77 | // data.startsWith(`${BASE_URL}${MESSAGE_PATH}`), 78 | assert.ok( 79 | data.startsWith(`${MESSAGE_PATH}`), 80 | `endpoint data should start with "${BASE_URL}${MESSAGE_PATH}", got: ${data}`, 81 | ) 82 | }) 83 | -------------------------------------------------------------------------------- /tests/concurrency.test.ts: -------------------------------------------------------------------------------- 1 | import { test } from 'node:test' 2 | import assert from 'node:assert/strict' 3 | import { randomInt } from 'node:crypto' 4 | import { performance } from 'node:perf_hooks' 5 | import { stdioToSse } from '../src/gateways/stdioToSse.js' 6 | import { getLogger } from '../src/lib/getLogger.js' 7 | import { Client } from '@modelcontextprotocol/sdk/client/index.js' 8 | import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js' 9 | 10 | const BASE_URL = 'http://localhost:11001' 11 | const SSE_PATH = '/sse' 12 | const CONCURRENCY = 1 13 | 14 | function makeLimiter(maxConcurrency: number) { 15 | let active = 0 16 | const queue: (() => void)[] = [] 17 | 18 | return async function (fn: () => Promise): Promise { 19 | if (active >= maxConcurrency) { 20 | // wait for a slot 21 | await new Promise((res) => queue.push(res)) 22 | } 23 | active++ 24 | try { 25 | return await fn() 26 | } finally { 27 | active-- 28 | // free up next waiter 29 | const next = queue.shift() 30 | if (next) next() 31 | } 32 | } 33 | } 34 | 35 | const limit = makeLimiter(CONCURRENCY) 36 | 37 | test.before(async () => { 38 | await stdioToSse({ 39 | stdioCmd: 'npx -y @modelcontextprotocol/server-everything', 40 | port: 11001, 41 | baseUrl: BASE_URL, 42 | ssePath: SSE_PATH, 43 | messagePath: '/message', 44 | logger: getLogger({ logLevel: 'info', outputTransport: 'stdio' }), 45 | corsOrigin: false, 46 | healthEndpoints: [], 47 | headers: {}, 48 | }) 49 | }) 50 | 51 | test.after(async () => { 52 | await new Promise((res) => setTimeout(res, 30000)) 53 | process.kill(process.pid, 'SIGINT') 54 | }) 55 | 56 | test('concurrent listTools → callTool', async () => { 57 | const succeededInstances: { id: number; text: string }[] = [] 58 | 59 | const runClient = async (id: number) => { 60 | const headers = { 61 | Authorization: 'Bearer YOUR_API_KEY', 62 | 'X-Instance-ID': String(id), 63 | } 64 | 65 | /** helper wrapper so TS sees correct `(input, init?)` signature */ 66 | const fetchWithHeaders = 67 | (hdrs: Record) => 68 | (input: RequestInfo | URL, init: RequestInit = {}) => 69 | fetch(input, { ...init, headers: { ...init.headers, ...hdrs } }) 70 | 71 | const transport = new SSEClientTransport(new URL(SSE_PATH, BASE_URL), { 72 | eventSourceInit: { fetch: fetchWithHeaders(headers) }, 73 | requestInit: { headers }, 74 | }) 75 | 76 | const client = new Client({ name: `load-${id}`, version: '0.0.0' }) 77 | 78 | const timing: Record = {} 79 | const span = async (label: string, fn: () => Promise) => { 80 | const t0 = performance.now() 81 | const out = await fn() 82 | timing[label] = performance.now() - t0 83 | return out 84 | } 85 | 86 | await client.connect(transport) 87 | 88 | const tools = await span('listTools', () => client.listTools()) 89 | assert.ok(Array.isArray(tools.tools), 'listTools() must return array') 90 | 91 | const rnd = randomInt(1, 51) 92 | const reply = await span('add', () => 93 | client.callTool({ name: 'add', arguments: { a: id, b: rnd } }, undefined), 94 | ) 95 | const content = reply.content as any 96 | const text = content && content[0]?.text 97 | console.log({ text }) 98 | assert.strictEqual(text, `The sum of ${id} and ${rnd} is ${id + rnd}.`) 99 | 100 | await client.close() 101 | console.log(`Instance ${id} timings:`, timing) 102 | succeededInstances.push({ 103 | id, 104 | text, 105 | }) 106 | } 107 | 108 | await Promise.all( 109 | Array.from({ length: CONCURRENCY }, (_, i) => 110 | limit(() => runClient(i + 1)), 111 | ), 112 | ) 113 | 114 | assert.strictEqual( 115 | succeededInstances.length, 116 | CONCURRENCY, 117 | 'All instances should succeed', 118 | ) 119 | 120 | console.log({ succeededInstances }) 121 | }) 122 | -------------------------------------------------------------------------------- /tests/protocolVersion.test.ts: -------------------------------------------------------------------------------- 1 | import { test } from 'node:test' 2 | import assert from 'node:assert/strict' 3 | import { spawn, ChildProcess } from 'child_process' 4 | 5 | import { Client } from 'prev-modelcontextprotocol-sdk/client/index.js' 6 | import { StdioClientTransport } from 'prev-modelcontextprotocol-sdk/client/stdio.js' 7 | 8 | const MCP_PORT = 11003 9 | const MCP_URL = `http://localhost:${MCP_PORT}/sse` 10 | 11 | let serverProc: ChildProcess | undefined 12 | 13 | function spawnMcpServer(): Promise { 14 | return new Promise((res, rej) => { 15 | const proc = spawn( 16 | `PORT=${MCP_PORT} npx -y @modelcontextprotocol/server-everything sse`, 17 | { shell: true, stdio: ['inherit', 'pipe', 'inherit'] }, 18 | ) 19 | 20 | proc.stdout.setEncoding('utf8') 21 | proc.stdout.on('data', (chunk: string) => { 22 | if (chunk.includes('Server is running on port')) { 23 | res(proc) 24 | } 25 | }) 26 | 27 | proc.on('error', rej) 28 | }) 29 | } 30 | 31 | test.before(async () => { 32 | serverProc = await spawnMcpServer() 33 | }) 34 | 35 | test.after(() => serverProc?.kill('SIGINT')) 36 | 37 | test('protocol version is passed', async () => { 38 | const gatewayCmd = ['npm', 'run', 'start', '--', '--sse', MCP_URL] 39 | 40 | const transport = new StdioClientTransport({ 41 | command: gatewayCmd[0], 42 | args: gatewayCmd.slice(1), 43 | }) 44 | 45 | const client = new Client({ name: 'gateway-test', version: '1.0.0' }) 46 | await client.connect(transport) 47 | 48 | const { tools } = await client.listTools() 49 | assert.ok(tools.some((t) => t.name === 'add')) 50 | 51 | type Reply = { content: Array<{ text: string }> } 52 | const reply = (await client.callTool({ 53 | name: 'add', 54 | arguments: { a: 2, b: 3 }, 55 | })) as Reply 56 | 57 | assert.strictEqual(reply.content[0].text, 'The sum of 2 and 3 is 5.') 58 | await client.close() 59 | }) 60 | -------------------------------------------------------------------------------- /tests/streamableHttpToStdio.test.ts: -------------------------------------------------------------------------------- 1 | import { test } from 'node:test' 2 | import assert from 'node:assert/strict' 3 | import { spawn, ChildProcess } from 'child_process' 4 | 5 | import { Client } from '@modelcontextprotocol/sdk/client/index.js' 6 | import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js' 7 | 8 | const MCP_PORT = 11002 9 | const MCP_URL = `http://localhost:${MCP_PORT}/mcp` 10 | 11 | let serverProc: ChildProcess | undefined 12 | 13 | function spawnMcpServer(): Promise { 14 | return new Promise((res, rej) => { 15 | const proc = spawn( 16 | `PORT=${MCP_PORT} npx -y @modelcontextprotocol/server-everything streamableHttp`, 17 | { shell: true, stdio: ['inherit', 'pipe', 'inherit'] }, 18 | ) 19 | 20 | proc.stdout.setEncoding('utf8') 21 | proc.stdout.on('data', (chunk: string) => { 22 | if (chunk.includes('MCP Streamable HTTP Server listening')) { 23 | res(proc) 24 | } 25 | }) 26 | 27 | proc.on('error', rej) 28 | }) 29 | } 30 | 31 | test.before(async () => { 32 | serverProc = await spawnMcpServer() 33 | }) 34 | 35 | test.after(() => serverProc?.kill('SIGINT')) 36 | 37 | test('streamableHttpToStdio listTools and callTool', async () => { 38 | const gatewayCmd = ['npm', 'run', 'start', '--', '--streamableHttp', MCP_URL] 39 | 40 | const transport = new StdioClientTransport({ 41 | command: gatewayCmd[0], 42 | args: gatewayCmd.slice(1), 43 | }) 44 | 45 | const client = new Client({ name: 'gateway-test', version: '1.0.0' }) 46 | await client.connect(transport) 47 | 48 | const { tools } = await client.listTools() 49 | assert.ok(tools.some((t) => t.name === 'add')) 50 | 51 | type Reply = { content: Array<{ text: string }> } 52 | const reply = (await client.callTool({ 53 | name: 'add', 54 | arguments: { a: 2, b: 3 }, 55 | })) as Reply 56 | 57 | assert.strictEqual(reply.content[0].text, 'The sum of 2 and 3 is 5.') 58 | await client.close() 59 | }) 60 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "rootDir": "src", 5 | "outDir": "dist" 6 | }, 7 | "include": ["src/**/*"] 8 | } 9 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "NodeNext", 4 | "moduleResolution": "NodeNext", 5 | "target": "ES2022", 6 | "strict": true, 7 | "esModuleInterop": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "outDir": "dist" 10 | }, 11 | "include": ["src/**/*", "tests/**/*"] 12 | } 13 | --------------------------------------------------------------------------------