├── .gitignore ├── README.md ├── README_ja.md ├── events └── event.json ├── mcp-function ├── Makefile ├── esbuild.js ├── package-lock.json ├── package.json ├── run.sh ├── src │ ├── client.ts │ └── server.ts └── tsconfig.json ├── samconfig.toml └── template.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.toptal.com/developers/gitignore/api/osx,node,linux,windows,sam 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=osx,node,linux,windows,sam 4 | 5 | ### Linux ### 6 | *~ 7 | 8 | # temporary files which can be created if a process still has a handle open of a deleted file 9 | .fuse_hidden* 10 | 11 | # KDE directory preferences 12 | .directory 13 | 14 | # Linux trash folder which might appear on any partition or disk 15 | .Trash-* 16 | 17 | # .nfs files are created when an open file is removed but is still being accessed 18 | .nfs* 19 | 20 | ### Node ### 21 | # Logs 22 | logs 23 | *.log 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | lerna-debug.log* 28 | 29 | # Diagnostic reports (https://nodejs.org/api/report.html) 30 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 31 | 32 | # Runtime data 33 | pids 34 | *.pid 35 | *.seed 36 | *.pid.lock 37 | 38 | # Directory for instrumented libs generated by jscoverage/JSCover 39 | lib-cov 40 | 41 | # Coverage directory used by tools like istanbul 42 | coverage 43 | *.lcov 44 | 45 | # nyc test coverage 46 | .nyc_output 47 | 48 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 49 | .grunt 50 | 51 | # Bower dependency directory (https://bower.io/) 52 | bower_components 53 | 54 | # node-waf configuration 55 | .lock-wscript 56 | 57 | # Compiled binary addons (https://nodejs.org/api/addons.html) 58 | build/Release 59 | 60 | # Dependency directories 61 | node_modules/ 62 | jspm_packages/ 63 | 64 | # TypeScript v1 declaration files 65 | typings/ 66 | 67 | # TypeScript cache 68 | *.tsbuildinfo 69 | 70 | # Optional npm cache directory 71 | .npm 72 | 73 | # Optional eslint cache 74 | .eslintcache 75 | 76 | # Optional stylelint cache 77 | .stylelintcache 78 | 79 | # Microbundle cache 80 | .rpt2_cache/ 81 | .rts2_cache_cjs/ 82 | .rts2_cache_es/ 83 | .rts2_cache_umd/ 84 | 85 | # Optional REPL history 86 | .node_repl_history 87 | 88 | # Output of 'npm pack' 89 | *.tgz 90 | 91 | # Yarn Integrity file 92 | .yarn-integrity 93 | 94 | # dotenv environment variables file 95 | .env 96 | .env.test 97 | .env*.local 98 | 99 | # parcel-bundler cache (https://parceljs.org/) 100 | .cache 101 | .parcel-cache 102 | 103 | # Next.js build output 104 | .next 105 | 106 | # Nuxt.js build / generate output 107 | .nuxt 108 | dist 109 | 110 | # Storybook build outputs 111 | .out 112 | .storybook-out 113 | storybook-static 114 | 115 | # rollup.js default build output 116 | dist/ 117 | 118 | # Gatsby files 119 | .cache/ 120 | # Comment in the public line in if your project uses Gatsby and not Next.js 121 | # https://nextjs.org/blog/next-9-1#public-directory-support 122 | # public 123 | 124 | # vuepress build output 125 | .vuepress/dist 126 | 127 | # Serverless directories 128 | .serverless/ 129 | 130 | # FuseBox cache 131 | .fusebox/ 132 | 133 | # DynamoDB Local files 134 | .dynamodb/ 135 | 136 | # TernJS port file 137 | .tern-port 138 | 139 | # Stores VSCode versions used for testing VSCode extensions 140 | .vscode-test 141 | 142 | # Temporary folders 143 | tmp/ 144 | temp/ 145 | 146 | ### OSX ### 147 | # General 148 | .DS_Store 149 | .AppleDouble 150 | .LSOverride 151 | 152 | # Icon must end with two \r 153 | Icon 154 | 155 | 156 | # Thumbnails 157 | ._* 158 | 159 | # Files that might appear in the root of a volume 160 | .DocumentRevisions-V100 161 | .fseventsd 162 | .Spotlight-V100 163 | .TemporaryItems 164 | .Trashes 165 | .VolumeIcon.icns 166 | .com.apple.timemachine.donotpresent 167 | 168 | # Directories potentially created on remote AFP share 169 | .AppleDB 170 | .AppleDesktop 171 | Network Trash Folder 172 | Temporary Items 173 | .apdisk 174 | 175 | ### SAM ### 176 | # Ignore build directories for the AWS Serverless Application Model (SAM) 177 | # Info: https://aws.amazon.com/serverless/sam/ 178 | # Docs: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-reference.html 179 | 180 | **/.aws-sam 181 | 182 | ### Windows ### 183 | # Windows thumbnail cache files 184 | Thumbs.db 185 | Thumbs.db:encryptable 186 | ehthumbs.db 187 | ehthumbs_vista.db 188 | 189 | # Dump file 190 | *.stackdump 191 | 192 | # Folder config file 193 | [Dd]esktop.ini 194 | 195 | # Recycle Bin used on file shares 196 | $RECYCLE.BIN/ 197 | 198 | # Windows Installer files 199 | *.cab 200 | *.msi 201 | *.msix 202 | *.msm 203 | *.msp 204 | 205 | # Windows shortcuts 206 | *.lnk 207 | 208 | # End of https://www.toptal.com/developers/gitignore/api/osx,node,linux,windows,sam 209 | mcp-function/output 210 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Streamable MCP Lambda Function 2 | 3 | This project is a serverless application that implements a Streamable HTTP API using the Model Context Protocol (MCP) on AWS Lambda. 4 | 5 | ## Project Overview 6 | 7 | This application deploys a Lambda function that supports response streaming using AWS SAM (Serverless Application Model). The main features include: 8 | 9 | - Tool invocation functionality using the Model Context Protocol (MCP) 10 | - Real-time responses utilizing Lambda Response Streaming 11 | - Implementation examples of simple greeting tools and notification capabilities 12 | 13 | ## About the Libraries Used 14 | 15 | This project uses the Model Context Protocol (MCP) TypeScript library. 16 | 17 | - **Repository**: [github.com/anthropics/model-context-protocol](https://github.com/anthropics/model-context-protocol) 18 | 19 | ## Architecture 20 | 21 | This application consists of the following components: 22 | 23 | - **MCPStreamableFunction**: Lambda function using Node.js 22.x runtime 24 | - **Lambda Adapter Layer**: Layer to support response streaming 25 | - **Function URL**: Endpoint for direct access to the Lambda function without authentication 26 | 27 | ## Prerequisites 28 | 29 | To use this project, you need: 30 | 31 | - [AWS CLI](https://aws.amazon.com/cli/) 32 | - [SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) 33 | - [Node.js 22.x](https://nodejs.org/en/) 34 | - [Docker](https://www.docker.com/products/docker-desktop) 35 | 36 | ## Setup and Deployment 37 | 38 | ### Setting up the Local Development Environment 39 | 40 | ```bash 41 | # Clone the repository 42 | git clone https://github.com/moritalous/mcp-streamablehttp-lambda-sample.git 43 | # Navigate to the project directory 44 | cd mcp-streamablehttp-lambda-sample 45 | 46 | # Install dependencies 47 | cd mcp-function 48 | npm install 49 | cd .. 50 | ``` 51 | 52 | ### Build and Deploy 53 | 54 | ```bash 55 | # Build the application 56 | sam build 57 | 58 | # Deploy the application (interactive for the first time) 59 | sam deploy --guided 60 | ``` 61 | 62 | During deployment, you will be prompted to enter the following information: 63 | 64 | - **Stack Name**: Name of the CloudFormation stack (e.g., mcp-server-streamable-http) 65 | - **AWS Region**: Region to deploy to 66 | - **Confirm changes before deploy**: Whether to confirm changes 67 | - **Allow SAM CLI IAM role creation**: Whether to allow IAM role creation 68 | - **Save arguments to samconfig.toml**: Whether to save the configuration 69 | 70 | After deployment completes, the Lambda Function URL will be output. You can use this URL to access the API. 71 | 72 | ## Features and Endpoints 73 | 74 | This application provides the following endpoints: 75 | 76 | - **POST /mcp**: Initialize and send MCP requests 77 | - **GET /mcp**: Method not allowed (returns 405) 78 | - **DELETE /mcp**: Method not allowed (returns 405) 79 | 80 | ## Implemented Tools 81 | 82 | This sample application implements the following tools: 83 | 84 | 1. **greet**: A simple greeting tool 85 | - Parameter: `name` (string) 86 | 87 | 2. **multi-greet**: A tool that sends multiple greetings with notifications 88 | - Parameter: `name` (string) 89 | 90 | 3. **greeting-template**: A prompt template for generating greetings 91 | - Parameter: `name` (string) 92 | 93 | 4. **greeting-resource**: A resource that provides a default greeting 94 | 95 | ## Client Implementation 96 | 97 | A client implementation example is available in `mcp-function/src/client.ts`. This client provides an interactive command-line interface to: 98 | 99 | 1. Connect to the server 100 | 2. List available tools, prompts, and resources 101 | 3. Call tools with arguments 102 | 4. Get prompts with arguments 103 | 5. Handle notifications from the server 104 | 6. Manage session termination and reconnection 105 | 106 | ## Testing Connection from Local to Lambda 107 | 108 | ```bash 109 | cd mcp-function 110 | 111 | MCP_SERVER_URL=https://*****.lambda-url.us-east-1.on.aws/mcp npm run dev:client 112 | ``` 113 | 114 | ## Resource Cleanup 115 | 116 | To remove resources when no longer needed: 117 | 118 | ```bash 119 | sam delete --stack-name 120 | ``` 121 | 122 | ## Additional Information 123 | 124 | - [AWS SAM Developer Guide](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html) 125 | - [Lambda Response Streaming](https://docs.aws.amazon.com/lambda/latest/dg/configuration-response-streaming.html) 126 | - [Model Context Protocol](https://github.com/anthropics/model-context-protocol) 127 | -------------------------------------------------------------------------------- /README_ja.md: -------------------------------------------------------------------------------- 1 | # Streamable MCP Lambda Function 2 | 3 | このプロジェクトは、AWS Lambda上でModel Context Protocol (MCP)を使用したStreamable HTTP APIを実装したサーバーレスアプリケーションです。 4 | 5 | ## プロジェクト概要 6 | 7 | このアプリケーションは、AWS SAM (Serverless Application Model)を使用して、レスポンスストリーミングをサポートするLambda関数をデプロイします。主な機能は以下の通りです: 8 | 9 | - Model Context Protocol (MCP)を使用したツール呼び出し機能 10 | - Lambda Response Streaming機能を活用したリアルタイムレスポンス 11 | - 簡単な挨拶ツールと通知機能の実装例 12 | 13 | ## 使用ライブラリについて 14 | 15 | このプロジェクトはModel Context Protocol (MCP) TypeScriptライブラリを使用しています。 16 | 17 | - **リポジトリ**: [github.com/anthropics/model-context-protocol](https://github.com/anthropics/model-context-protocol) 18 | 19 | ## アーキテクチャ 20 | 21 | このアプリケーションは以下のコンポーネントで構成されています: 22 | 23 | - **MCPStreamableFunction**: Node.js 22.xランタイムを使用したLambda関数 24 | - **Lambda Adapter Layer**: レスポンスストリーミングをサポートするためのレイヤー 25 | - **Function URL**: 認証なしでLambda関数に直接アクセスするためのエンドポイント 26 | 27 | ## 前提条件 28 | 29 | このプロジェクトを使用するには以下が必要です: 30 | 31 | - [AWS CLI](https://aws.amazon.com/cli/) 32 | - [SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) 33 | - [Node.js 22.x](https://nodejs.org/en/) 34 | - [Docker](https://www.docker.com/products/docker-desktop) 35 | 36 | ## セットアップと展開 37 | 38 | ### ローカル開発環境のセットアップ 39 | 40 | ```bash 41 | # リポジトリをClone 42 | git clone https://github.com/moritalous/mcp-streamablehttp-lambda-sample.git 43 | # プロジェクトディレクトリに移動 44 | cd mcp-streamablehttp-lambda-sample 45 | 46 | # 依存関係のインストール 47 | cd mcp-function 48 | npm install 49 | cd .. 50 | ``` 51 | 52 | ### ビルドとデプロイ 53 | 54 | ```bash 55 | # アプリケーションのビルド 56 | sam build 57 | 58 | # アプリケーションのデプロイ(初回は対話形式) 59 | sam deploy --guided 60 | ``` 61 | 62 | デプロイ時に以下の情報を入力します: 63 | 64 | - **Stack Name**: CloudFormationスタックの名前(例:mcp-server-streamable-http) 65 | - **AWS Region**: デプロイするリージョン 66 | - **Confirm changes before deploy**: 変更を確認するかどうか 67 | - **Allow SAM CLI IAM role creation**: IAMロールの作成を許可するかどうか 68 | - **Save arguments to samconfig.toml**: 設定を保存するかどうか 69 | 70 | デプロイが完了すると、Lambda Function URLが出力されます。このURLを使用してAPIにアクセスできます。 71 | 72 | ## 機能とエンドポイント 73 | 74 | このアプリケーションは以下のエンドポイントを提供します: 75 | 76 | - **POST /mcp**: MCPリクエストの初期化と送信 77 | - **GET /mcp**: 許可されていないメソッド(405を返す) 78 | - **DELETE /mcp**: 許可されていないメソッド(405を返す) 79 | 80 | ## 実装されているツール 81 | 82 | このサンプルアプリケーションには以下のツールが実装されています: 83 | 84 | 1. **greet**: シンプルな挨拶ツール 85 | - パラメータ: `name` (文字列) 86 | 87 | 2. **multi-greet**: 通知機能付きで複数の挨拶を送信するツール 88 | - パラメータ: `name` (文字列) 89 | 90 | 3. **greeting-template**: 挨拶を生成するためのプロンプトテンプレート 91 | - パラメータ: `name` (文字列) 92 | 93 | 4. **greeting-resource**: デフォルトの挨拶を提供するリソース 94 | 95 | ## クライアント実装 96 | 97 | クライアント側の実装例は `mcp-function/src/client.ts` にあります。このクライアントは以下の機能を提供する対話型コマンドラインインターフェースを提供します: 98 | 99 | 1. サーバーへの接続 100 | 2. 利用可能なツール、プロンプト、リソースの一覧取得 101 | 3. 引数を指定したツールの呼び出し 102 | 4. 引数を指定したプロンプトの取得 103 | 5. サーバーからの通知の処理 104 | 6. セッション終了と再接続の管理 105 | 106 | ## ローカルからLambdaへの接続テスト 107 | 108 | ```bash 109 | cd mcp-function 110 | 111 | MCP_SERVER_URL=https://*****.lambda-url.us-east-1.on.aws/mcp npm run dev:client 112 | ``` 113 | 114 | ## リソースのクリーンアップ 115 | 116 | 不要になったリソースを削除するには: 117 | 118 | ```bash 119 | sam delete --stack-name 120 | ``` 121 | 122 | ## 詳細情報 123 | 124 | - [AWS SAM デベロッパーガイド](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html) 125 | - [Lambda Response Streaming](https://docs.aws.amazon.com/lambda/latest/dg/configuration-response-streaming.html) 126 | - [Model Context Protocol](https://github.com/anthropics/model-context-protocol) 127 | -------------------------------------------------------------------------------- /events/event.json: -------------------------------------------------------------------------------- 1 | { 2 | "body": "{\"message\": \"hello world\"}", 3 | "resource": "/{proxy+}", 4 | "path": "/path/to/resource", 5 | "httpMethod": "POST", 6 | "isBase64Encoded": false, 7 | "queryStringParameters": { 8 | "foo": "bar" 9 | }, 10 | "pathParameters": { 11 | "proxy": "/path/to/resource" 12 | }, 13 | "stageVariables": { 14 | "baz": "qux" 15 | }, 16 | "headers": { 17 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 18 | "Accept-Encoding": "gzip, deflate, sdch", 19 | "Accept-Language": "en-US,en;q=0.8", 20 | "Cache-Control": "max-age=0", 21 | "CloudFront-Forwarded-Proto": "https", 22 | "CloudFront-Is-Desktop-Viewer": "true", 23 | "CloudFront-Is-Mobile-Viewer": "false", 24 | "CloudFront-Is-SmartTV-Viewer": "false", 25 | "CloudFront-Is-Tablet-Viewer": "false", 26 | "CloudFront-Viewer-Country": "US", 27 | "Host": "1234567890.execute-api.us-east-1.amazonaws.com", 28 | "Upgrade-Insecure-Requests": "1", 29 | "User-Agent": "Custom User Agent String", 30 | "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", 31 | "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==", 32 | "X-Forwarded-For": "127.0.0.1, 127.0.0.2", 33 | "X-Forwarded-Port": "443", 34 | "X-Forwarded-Proto": "https" 35 | }, 36 | "requestContext": { 37 | "accountId": "123456789012", 38 | "resourceId": "123456", 39 | "stage": "prod", 40 | "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", 41 | "requestTime": "09/Apr/2015:12:34:56 +0000", 42 | "requestTimeEpoch": 1428582896000, 43 | "identity": { 44 | "cognitoIdentityPoolId": null, 45 | "accountId": null, 46 | "cognitoIdentityId": null, 47 | "caller": null, 48 | "accessKey": null, 49 | "sourceIp": "127.0.0.1", 50 | "cognitoAuthenticationType": null, 51 | "cognitoAuthenticationProvider": null, 52 | "userArn": null, 53 | "userAgent": "Custom User Agent String", 54 | "user": null 55 | }, 56 | "path": "/prod/path/to/resource", 57 | "resourcePath": "/{proxy+}", 58 | "httpMethod": "POST", 59 | "apiId": "1234567890", 60 | "protocol": "HTTP/1.1" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /mcp-function/Makefile: -------------------------------------------------------------------------------- 1 | build-MCPStreamableFunction: 2 | mkdir -p $(ARTIFACTS_DIR) 3 | cp -r src run.sh package.json package-lock.json tsconfig.json esbuild.js $(ARTIFACTS_DIR) 4 | cd $(ARTIFACTS_DIR) && npm ci && npm run build 5 | cd $(ARTIFACTS_DIR) && node esbuild.js 6 | cd $(ARTIFACTS_DIR) && rm -rf src package.json package-lock.json tsconfig.json esbuild.js dist node_modules 7 | chmod +x $(ARTIFACTS_DIR)/run.sh 8 | -------------------------------------------------------------------------------- /mcp-function/esbuild.js: -------------------------------------------------------------------------------- 1 | const esbuild = require('esbuild'); 2 | const path = require('path'); 3 | 4 | esbuild.build({ 5 | entryPoints: ['dist/server.js'], 6 | bundle: true, 7 | minify: true, 8 | platform: 'node', 9 | target: 'node22', 10 | outfile: 'output/bundle.js', 11 | external: ['aws-sdk', '@aws-sdk/*'], // Exclude AWS SDK as it already exists in the Lambda environment 12 | metafile: true, 13 | }).then(result => { 14 | // Output bundle size information 15 | const outputSize = Object.entries(result.metafile.outputs).reduce((acc, [file, data]) => { 16 | return acc + data.bytes; 17 | }, 0); 18 | console.log(`Bundle size: ${(outputSize / 1024 / 1024).toFixed(2)} MB`); 19 | }).catch(() => process.exit(1)); 20 | -------------------------------------------------------------------------------- /mcp-function/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mcp-streamablehttp-lambda", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "mcp-streamablehttp-lambda", 9 | "version": "1.0.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "@modelcontextprotocol/sdk": "^1.10.1", 13 | "body-parser": "^2.2.0", 14 | "esbuild": "^0.25.2", 15 | "express": "^5.1.0", 16 | "zod": "^3.22.4", 17 | "zod-to-json-schema": "^3.22.3" 18 | }, 19 | "devDependencies": { 20 | "@types/express": "^5.0.1", 21 | "@types/node": "^20.11.30", 22 | "ts-node": "^10.9.2", 23 | "typescript": "^5.4.5" 24 | } 25 | }, 26 | "node_modules/@cspotcode/source-map-support": { 27 | "version": "0.8.1", 28 | "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", 29 | "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", 30 | "dev": true, 31 | "license": "MIT", 32 | "dependencies": { 33 | "@jridgewell/trace-mapping": "0.3.9" 34 | }, 35 | "engines": { 36 | "node": ">=12" 37 | } 38 | }, 39 | "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { 40 | "version": "0.3.9", 41 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", 42 | "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", 43 | "dev": true, 44 | "license": "MIT", 45 | "dependencies": { 46 | "@jridgewell/resolve-uri": "^3.0.3", 47 | "@jridgewell/sourcemap-codec": "^1.4.10" 48 | } 49 | }, 50 | "node_modules/@esbuild/aix-ppc64": { 51 | "version": "0.25.2", 52 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz", 53 | "integrity": "sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==", 54 | "cpu": [ 55 | "ppc64" 56 | ], 57 | "license": "MIT", 58 | "optional": true, 59 | "os": [ 60 | "aix" 61 | ], 62 | "engines": { 63 | "node": ">=18" 64 | } 65 | }, 66 | "node_modules/@esbuild/android-arm": { 67 | "version": "0.25.2", 68 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.2.tgz", 69 | "integrity": "sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==", 70 | "cpu": [ 71 | "arm" 72 | ], 73 | "license": "MIT", 74 | "optional": true, 75 | "os": [ 76 | "android" 77 | ], 78 | "engines": { 79 | "node": ">=18" 80 | } 81 | }, 82 | "node_modules/@esbuild/android-arm64": { 83 | "version": "0.25.2", 84 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz", 85 | "integrity": "sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==", 86 | "cpu": [ 87 | "arm64" 88 | ], 89 | "license": "MIT", 90 | "optional": true, 91 | "os": [ 92 | "android" 93 | ], 94 | "engines": { 95 | "node": ">=18" 96 | } 97 | }, 98 | "node_modules/@esbuild/android-x64": { 99 | "version": "0.25.2", 100 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.2.tgz", 101 | "integrity": "sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==", 102 | "cpu": [ 103 | "x64" 104 | ], 105 | "license": "MIT", 106 | "optional": true, 107 | "os": [ 108 | "android" 109 | ], 110 | "engines": { 111 | "node": ">=18" 112 | } 113 | }, 114 | "node_modules/@esbuild/darwin-arm64": { 115 | "version": "0.25.2", 116 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz", 117 | "integrity": "sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==", 118 | "cpu": [ 119 | "arm64" 120 | ], 121 | "license": "MIT", 122 | "optional": true, 123 | "os": [ 124 | "darwin" 125 | ], 126 | "engines": { 127 | "node": ">=18" 128 | } 129 | }, 130 | "node_modules/@esbuild/darwin-x64": { 131 | "version": "0.25.2", 132 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz", 133 | "integrity": "sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==", 134 | "cpu": [ 135 | "x64" 136 | ], 137 | "license": "MIT", 138 | "optional": true, 139 | "os": [ 140 | "darwin" 141 | ], 142 | "engines": { 143 | "node": ">=18" 144 | } 145 | }, 146 | "node_modules/@esbuild/freebsd-arm64": { 147 | "version": "0.25.2", 148 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz", 149 | "integrity": "sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==", 150 | "cpu": [ 151 | "arm64" 152 | ], 153 | "license": "MIT", 154 | "optional": true, 155 | "os": [ 156 | "freebsd" 157 | ], 158 | "engines": { 159 | "node": ">=18" 160 | } 161 | }, 162 | "node_modules/@esbuild/freebsd-x64": { 163 | "version": "0.25.2", 164 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz", 165 | "integrity": "sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==", 166 | "cpu": [ 167 | "x64" 168 | ], 169 | "license": "MIT", 170 | "optional": true, 171 | "os": [ 172 | "freebsd" 173 | ], 174 | "engines": { 175 | "node": ">=18" 176 | } 177 | }, 178 | "node_modules/@esbuild/linux-arm": { 179 | "version": "0.25.2", 180 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz", 181 | "integrity": "sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==", 182 | "cpu": [ 183 | "arm" 184 | ], 185 | "license": "MIT", 186 | "optional": true, 187 | "os": [ 188 | "linux" 189 | ], 190 | "engines": { 191 | "node": ">=18" 192 | } 193 | }, 194 | "node_modules/@esbuild/linux-arm64": { 195 | "version": "0.25.2", 196 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz", 197 | "integrity": "sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==", 198 | "cpu": [ 199 | "arm64" 200 | ], 201 | "license": "MIT", 202 | "optional": true, 203 | "os": [ 204 | "linux" 205 | ], 206 | "engines": { 207 | "node": ">=18" 208 | } 209 | }, 210 | "node_modules/@esbuild/linux-ia32": { 211 | "version": "0.25.2", 212 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz", 213 | "integrity": "sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==", 214 | "cpu": [ 215 | "ia32" 216 | ], 217 | "license": "MIT", 218 | "optional": true, 219 | "os": [ 220 | "linux" 221 | ], 222 | "engines": { 223 | "node": ">=18" 224 | } 225 | }, 226 | "node_modules/@esbuild/linux-loong64": { 227 | "version": "0.25.2", 228 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz", 229 | "integrity": "sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==", 230 | "cpu": [ 231 | "loong64" 232 | ], 233 | "license": "MIT", 234 | "optional": true, 235 | "os": [ 236 | "linux" 237 | ], 238 | "engines": { 239 | "node": ">=18" 240 | } 241 | }, 242 | "node_modules/@esbuild/linux-mips64el": { 243 | "version": "0.25.2", 244 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz", 245 | "integrity": "sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==", 246 | "cpu": [ 247 | "mips64el" 248 | ], 249 | "license": "MIT", 250 | "optional": true, 251 | "os": [ 252 | "linux" 253 | ], 254 | "engines": { 255 | "node": ">=18" 256 | } 257 | }, 258 | "node_modules/@esbuild/linux-ppc64": { 259 | "version": "0.25.2", 260 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz", 261 | "integrity": "sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==", 262 | "cpu": [ 263 | "ppc64" 264 | ], 265 | "license": "MIT", 266 | "optional": true, 267 | "os": [ 268 | "linux" 269 | ], 270 | "engines": { 271 | "node": ">=18" 272 | } 273 | }, 274 | "node_modules/@esbuild/linux-riscv64": { 275 | "version": "0.25.2", 276 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz", 277 | "integrity": "sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==", 278 | "cpu": [ 279 | "riscv64" 280 | ], 281 | "license": "MIT", 282 | "optional": true, 283 | "os": [ 284 | "linux" 285 | ], 286 | "engines": { 287 | "node": ">=18" 288 | } 289 | }, 290 | "node_modules/@esbuild/linux-s390x": { 291 | "version": "0.25.2", 292 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz", 293 | "integrity": "sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==", 294 | "cpu": [ 295 | "s390x" 296 | ], 297 | "license": "MIT", 298 | "optional": true, 299 | "os": [ 300 | "linux" 301 | ], 302 | "engines": { 303 | "node": ">=18" 304 | } 305 | }, 306 | "node_modules/@esbuild/linux-x64": { 307 | "version": "0.25.2", 308 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz", 309 | "integrity": "sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==", 310 | "cpu": [ 311 | "x64" 312 | ], 313 | "license": "MIT", 314 | "optional": true, 315 | "os": [ 316 | "linux" 317 | ], 318 | "engines": { 319 | "node": ">=18" 320 | } 321 | }, 322 | "node_modules/@esbuild/netbsd-arm64": { 323 | "version": "0.25.2", 324 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz", 325 | "integrity": "sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==", 326 | "cpu": [ 327 | "arm64" 328 | ], 329 | "license": "MIT", 330 | "optional": true, 331 | "os": [ 332 | "netbsd" 333 | ], 334 | "engines": { 335 | "node": ">=18" 336 | } 337 | }, 338 | "node_modules/@esbuild/netbsd-x64": { 339 | "version": "0.25.2", 340 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz", 341 | "integrity": "sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==", 342 | "cpu": [ 343 | "x64" 344 | ], 345 | "license": "MIT", 346 | "optional": true, 347 | "os": [ 348 | "netbsd" 349 | ], 350 | "engines": { 351 | "node": ">=18" 352 | } 353 | }, 354 | "node_modules/@esbuild/openbsd-arm64": { 355 | "version": "0.25.2", 356 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz", 357 | "integrity": "sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==", 358 | "cpu": [ 359 | "arm64" 360 | ], 361 | "license": "MIT", 362 | "optional": true, 363 | "os": [ 364 | "openbsd" 365 | ], 366 | "engines": { 367 | "node": ">=18" 368 | } 369 | }, 370 | "node_modules/@esbuild/openbsd-x64": { 371 | "version": "0.25.2", 372 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz", 373 | "integrity": "sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==", 374 | "cpu": [ 375 | "x64" 376 | ], 377 | "license": "MIT", 378 | "optional": true, 379 | "os": [ 380 | "openbsd" 381 | ], 382 | "engines": { 383 | "node": ">=18" 384 | } 385 | }, 386 | "node_modules/@esbuild/sunos-x64": { 387 | "version": "0.25.2", 388 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz", 389 | "integrity": "sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==", 390 | "cpu": [ 391 | "x64" 392 | ], 393 | "license": "MIT", 394 | "optional": true, 395 | "os": [ 396 | "sunos" 397 | ], 398 | "engines": { 399 | "node": ">=18" 400 | } 401 | }, 402 | "node_modules/@esbuild/win32-arm64": { 403 | "version": "0.25.2", 404 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz", 405 | "integrity": "sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==", 406 | "cpu": [ 407 | "arm64" 408 | ], 409 | "license": "MIT", 410 | "optional": true, 411 | "os": [ 412 | "win32" 413 | ], 414 | "engines": { 415 | "node": ">=18" 416 | } 417 | }, 418 | "node_modules/@esbuild/win32-ia32": { 419 | "version": "0.25.2", 420 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz", 421 | "integrity": "sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==", 422 | "cpu": [ 423 | "ia32" 424 | ], 425 | "license": "MIT", 426 | "optional": true, 427 | "os": [ 428 | "win32" 429 | ], 430 | "engines": { 431 | "node": ">=18" 432 | } 433 | }, 434 | "node_modules/@esbuild/win32-x64": { 435 | "version": "0.25.2", 436 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz", 437 | "integrity": "sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==", 438 | "cpu": [ 439 | "x64" 440 | ], 441 | "license": "MIT", 442 | "optional": true, 443 | "os": [ 444 | "win32" 445 | ], 446 | "engines": { 447 | "node": ">=18" 448 | } 449 | }, 450 | "node_modules/@jridgewell/resolve-uri": { 451 | "version": "3.1.2", 452 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 453 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 454 | "dev": true, 455 | "license": "MIT", 456 | "engines": { 457 | "node": ">=6.0.0" 458 | } 459 | }, 460 | "node_modules/@jridgewell/sourcemap-codec": { 461 | "version": "1.5.0", 462 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 463 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 464 | "dev": true, 465 | "license": "MIT" 466 | }, 467 | "node_modules/@modelcontextprotocol/sdk": { 468 | "version": "1.10.1", 469 | "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.10.1.tgz", 470 | "integrity": "sha512-xNYdFdkJqEfIaTVP1gPKoEvluACHZsHZegIoICX8DM1o6Qf3G5u2BQJHmgd0n4YgRPqqK/u1ujQvrgAxxSJT9w==", 471 | "license": "MIT", 472 | "dependencies": { 473 | "content-type": "^1.0.5", 474 | "cors": "^2.8.5", 475 | "cross-spawn": "^7.0.3", 476 | "eventsource": "^3.0.2", 477 | "express": "^5.0.1", 478 | "express-rate-limit": "^7.5.0", 479 | "pkce-challenge": "^5.0.0", 480 | "raw-body": "^3.0.0", 481 | "zod": "^3.23.8", 482 | "zod-to-json-schema": "^3.24.1" 483 | }, 484 | "engines": { 485 | "node": ">=18" 486 | } 487 | }, 488 | "node_modules/@tsconfig/node10": { 489 | "version": "1.0.11", 490 | "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", 491 | "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", 492 | "dev": true, 493 | "license": "MIT" 494 | }, 495 | "node_modules/@tsconfig/node12": { 496 | "version": "1.0.11", 497 | "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", 498 | "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", 499 | "dev": true, 500 | "license": "MIT" 501 | }, 502 | "node_modules/@tsconfig/node14": { 503 | "version": "1.0.3", 504 | "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", 505 | "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", 506 | "dev": true, 507 | "license": "MIT" 508 | }, 509 | "node_modules/@tsconfig/node16": { 510 | "version": "1.0.4", 511 | "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", 512 | "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", 513 | "dev": true, 514 | "license": "MIT" 515 | }, 516 | "node_modules/@types/body-parser": { 517 | "version": "1.19.5", 518 | "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", 519 | "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", 520 | "dev": true, 521 | "license": "MIT", 522 | "dependencies": { 523 | "@types/connect": "*", 524 | "@types/node": "*" 525 | } 526 | }, 527 | "node_modules/@types/connect": { 528 | "version": "3.4.38", 529 | "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", 530 | "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", 531 | "dev": true, 532 | "license": "MIT", 533 | "dependencies": { 534 | "@types/node": "*" 535 | } 536 | }, 537 | "node_modules/@types/express": { 538 | "version": "5.0.1", 539 | "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.1.tgz", 540 | "integrity": "sha512-UZUw8vjpWFXuDnjFTh7/5c2TWDlQqeXHi6hcN7F2XSVT5P+WmUnnbFS3KA6Jnc6IsEqI2qCVu2bK0R0J4A8ZQQ==", 541 | "dev": true, 542 | "license": "MIT", 543 | "dependencies": { 544 | "@types/body-parser": "*", 545 | "@types/express-serve-static-core": "^5.0.0", 546 | "@types/serve-static": "*" 547 | } 548 | }, 549 | "node_modules/@types/express-serve-static-core": { 550 | "version": "5.0.6", 551 | "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.6.tgz", 552 | "integrity": "sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==", 553 | "dev": true, 554 | "license": "MIT", 555 | "dependencies": { 556 | "@types/node": "*", 557 | "@types/qs": "*", 558 | "@types/range-parser": "*", 559 | "@types/send": "*" 560 | } 561 | }, 562 | "node_modules/@types/http-errors": { 563 | "version": "2.0.4", 564 | "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", 565 | "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", 566 | "dev": true, 567 | "license": "MIT" 568 | }, 569 | "node_modules/@types/mime": { 570 | "version": "1.3.5", 571 | "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", 572 | "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", 573 | "dev": true, 574 | "license": "MIT" 575 | }, 576 | "node_modules/@types/node": { 577 | "version": "20.17.30", 578 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.30.tgz", 579 | "integrity": "sha512-7zf4YyHA+jvBNfVrk2Gtvs6x7E8V+YDW05bNfG2XkWDJfYRXrTiP/DsB2zSYTaHX0bGIujTBQdMVAhb+j7mwpg==", 580 | "dev": true, 581 | "license": "MIT", 582 | "dependencies": { 583 | "undici-types": "~6.19.2" 584 | } 585 | }, 586 | "node_modules/@types/qs": { 587 | "version": "6.9.18", 588 | "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", 589 | "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==", 590 | "dev": true, 591 | "license": "MIT" 592 | }, 593 | "node_modules/@types/range-parser": { 594 | "version": "1.2.7", 595 | "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", 596 | "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", 597 | "dev": true, 598 | "license": "MIT" 599 | }, 600 | "node_modules/@types/send": { 601 | "version": "0.17.4", 602 | "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", 603 | "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", 604 | "dev": true, 605 | "license": "MIT", 606 | "dependencies": { 607 | "@types/mime": "^1", 608 | "@types/node": "*" 609 | } 610 | }, 611 | "node_modules/@types/serve-static": { 612 | "version": "1.15.7", 613 | "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", 614 | "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", 615 | "dev": true, 616 | "license": "MIT", 617 | "dependencies": { 618 | "@types/http-errors": "*", 619 | "@types/node": "*", 620 | "@types/send": "*" 621 | } 622 | }, 623 | "node_modules/accepts": { 624 | "version": "2.0.0", 625 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", 626 | "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", 627 | "license": "MIT", 628 | "dependencies": { 629 | "mime-types": "^3.0.0", 630 | "negotiator": "^1.0.0" 631 | }, 632 | "engines": { 633 | "node": ">= 0.6" 634 | } 635 | }, 636 | "node_modules/acorn": { 637 | "version": "8.14.1", 638 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", 639 | "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", 640 | "dev": true, 641 | "license": "MIT", 642 | "bin": { 643 | "acorn": "bin/acorn" 644 | }, 645 | "engines": { 646 | "node": ">=0.4.0" 647 | } 648 | }, 649 | "node_modules/acorn-walk": { 650 | "version": "8.3.4", 651 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", 652 | "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", 653 | "dev": true, 654 | "license": "MIT", 655 | "dependencies": { 656 | "acorn": "^8.11.0" 657 | }, 658 | "engines": { 659 | "node": ">=0.4.0" 660 | } 661 | }, 662 | "node_modules/arg": { 663 | "version": "4.1.3", 664 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", 665 | "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", 666 | "dev": true, 667 | "license": "MIT" 668 | }, 669 | "node_modules/body-parser": { 670 | "version": "2.2.0", 671 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", 672 | "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", 673 | "license": "MIT", 674 | "dependencies": { 675 | "bytes": "^3.1.2", 676 | "content-type": "^1.0.5", 677 | "debug": "^4.4.0", 678 | "http-errors": "^2.0.0", 679 | "iconv-lite": "^0.6.3", 680 | "on-finished": "^2.4.1", 681 | "qs": "^6.14.0", 682 | "raw-body": "^3.0.0", 683 | "type-is": "^2.0.0" 684 | }, 685 | "engines": { 686 | "node": ">=18" 687 | } 688 | }, 689 | "node_modules/bytes": { 690 | "version": "3.1.2", 691 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 692 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 693 | "license": "MIT", 694 | "engines": { 695 | "node": ">= 0.8" 696 | } 697 | }, 698 | "node_modules/call-bind-apply-helpers": { 699 | "version": "1.0.2", 700 | "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", 701 | "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", 702 | "license": "MIT", 703 | "dependencies": { 704 | "es-errors": "^1.3.0", 705 | "function-bind": "^1.1.2" 706 | }, 707 | "engines": { 708 | "node": ">= 0.4" 709 | } 710 | }, 711 | "node_modules/call-bound": { 712 | "version": "1.0.4", 713 | "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", 714 | "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", 715 | "license": "MIT", 716 | "dependencies": { 717 | "call-bind-apply-helpers": "^1.0.2", 718 | "get-intrinsic": "^1.3.0" 719 | }, 720 | "engines": { 721 | "node": ">= 0.4" 722 | }, 723 | "funding": { 724 | "url": "https://github.com/sponsors/ljharb" 725 | } 726 | }, 727 | "node_modules/content-disposition": { 728 | "version": "1.0.0", 729 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", 730 | "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", 731 | "license": "MIT", 732 | "dependencies": { 733 | "safe-buffer": "5.2.1" 734 | }, 735 | "engines": { 736 | "node": ">= 0.6" 737 | } 738 | }, 739 | "node_modules/content-type": { 740 | "version": "1.0.5", 741 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 742 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 743 | "license": "MIT", 744 | "engines": { 745 | "node": ">= 0.6" 746 | } 747 | }, 748 | "node_modules/cookie": { 749 | "version": "0.7.2", 750 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", 751 | "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", 752 | "license": "MIT", 753 | "engines": { 754 | "node": ">= 0.6" 755 | } 756 | }, 757 | "node_modules/cookie-signature": { 758 | "version": "1.2.2", 759 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", 760 | "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", 761 | "license": "MIT", 762 | "engines": { 763 | "node": ">=6.6.0" 764 | } 765 | }, 766 | "node_modules/cors": { 767 | "version": "2.8.5", 768 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 769 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 770 | "license": "MIT", 771 | "dependencies": { 772 | "object-assign": "^4", 773 | "vary": "^1" 774 | }, 775 | "engines": { 776 | "node": ">= 0.10" 777 | } 778 | }, 779 | "node_modules/create-require": { 780 | "version": "1.1.1", 781 | "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", 782 | "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", 783 | "dev": true, 784 | "license": "MIT" 785 | }, 786 | "node_modules/cross-spawn": { 787 | "version": "7.0.6", 788 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", 789 | "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", 790 | "license": "MIT", 791 | "dependencies": { 792 | "path-key": "^3.1.0", 793 | "shebang-command": "^2.0.0", 794 | "which": "^2.0.1" 795 | }, 796 | "engines": { 797 | "node": ">= 8" 798 | } 799 | }, 800 | "node_modules/debug": { 801 | "version": "4.4.0", 802 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 803 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 804 | "license": "MIT", 805 | "dependencies": { 806 | "ms": "^2.1.3" 807 | }, 808 | "engines": { 809 | "node": ">=6.0" 810 | }, 811 | "peerDependenciesMeta": { 812 | "supports-color": { 813 | "optional": true 814 | } 815 | } 816 | }, 817 | "node_modules/depd": { 818 | "version": "2.0.0", 819 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 820 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 821 | "license": "MIT", 822 | "engines": { 823 | "node": ">= 0.8" 824 | } 825 | }, 826 | "node_modules/diff": { 827 | "version": "4.0.2", 828 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 829 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 830 | "dev": true, 831 | "license": "BSD-3-Clause", 832 | "engines": { 833 | "node": ">=0.3.1" 834 | } 835 | }, 836 | "node_modules/dunder-proto": { 837 | "version": "1.0.1", 838 | "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 839 | "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 840 | "license": "MIT", 841 | "dependencies": { 842 | "call-bind-apply-helpers": "^1.0.1", 843 | "es-errors": "^1.3.0", 844 | "gopd": "^1.2.0" 845 | }, 846 | "engines": { 847 | "node": ">= 0.4" 848 | } 849 | }, 850 | "node_modules/ee-first": { 851 | "version": "1.1.1", 852 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 853 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", 854 | "license": "MIT" 855 | }, 856 | "node_modules/encodeurl": { 857 | "version": "2.0.0", 858 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 859 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 860 | "license": "MIT", 861 | "engines": { 862 | "node": ">= 0.8" 863 | } 864 | }, 865 | "node_modules/es-define-property": { 866 | "version": "1.0.1", 867 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 868 | "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 869 | "license": "MIT", 870 | "engines": { 871 | "node": ">= 0.4" 872 | } 873 | }, 874 | "node_modules/es-errors": { 875 | "version": "1.3.0", 876 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 877 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 878 | "license": "MIT", 879 | "engines": { 880 | "node": ">= 0.4" 881 | } 882 | }, 883 | "node_modules/es-object-atoms": { 884 | "version": "1.1.1", 885 | "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", 886 | "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", 887 | "license": "MIT", 888 | "dependencies": { 889 | "es-errors": "^1.3.0" 890 | }, 891 | "engines": { 892 | "node": ">= 0.4" 893 | } 894 | }, 895 | "node_modules/esbuild": { 896 | "version": "0.25.2", 897 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz", 898 | "integrity": "sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==", 899 | "hasInstallScript": true, 900 | "license": "MIT", 901 | "bin": { 902 | "esbuild": "bin/esbuild" 903 | }, 904 | "engines": { 905 | "node": ">=18" 906 | }, 907 | "optionalDependencies": { 908 | "@esbuild/aix-ppc64": "0.25.2", 909 | "@esbuild/android-arm": "0.25.2", 910 | "@esbuild/android-arm64": "0.25.2", 911 | "@esbuild/android-x64": "0.25.2", 912 | "@esbuild/darwin-arm64": "0.25.2", 913 | "@esbuild/darwin-x64": "0.25.2", 914 | "@esbuild/freebsd-arm64": "0.25.2", 915 | "@esbuild/freebsd-x64": "0.25.2", 916 | "@esbuild/linux-arm": "0.25.2", 917 | "@esbuild/linux-arm64": "0.25.2", 918 | "@esbuild/linux-ia32": "0.25.2", 919 | "@esbuild/linux-loong64": "0.25.2", 920 | "@esbuild/linux-mips64el": "0.25.2", 921 | "@esbuild/linux-ppc64": "0.25.2", 922 | "@esbuild/linux-riscv64": "0.25.2", 923 | "@esbuild/linux-s390x": "0.25.2", 924 | "@esbuild/linux-x64": "0.25.2", 925 | "@esbuild/netbsd-arm64": "0.25.2", 926 | "@esbuild/netbsd-x64": "0.25.2", 927 | "@esbuild/openbsd-arm64": "0.25.2", 928 | "@esbuild/openbsd-x64": "0.25.2", 929 | "@esbuild/sunos-x64": "0.25.2", 930 | "@esbuild/win32-arm64": "0.25.2", 931 | "@esbuild/win32-ia32": "0.25.2", 932 | "@esbuild/win32-x64": "0.25.2" 933 | } 934 | }, 935 | "node_modules/escape-html": { 936 | "version": "1.0.3", 937 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 938 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", 939 | "license": "MIT" 940 | }, 941 | "node_modules/etag": { 942 | "version": "1.8.1", 943 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 944 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 945 | "license": "MIT", 946 | "engines": { 947 | "node": ">= 0.6" 948 | } 949 | }, 950 | "node_modules/eventsource": { 951 | "version": "3.0.6", 952 | "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.6.tgz", 953 | "integrity": "sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA==", 954 | "license": "MIT", 955 | "dependencies": { 956 | "eventsource-parser": "^3.0.1" 957 | }, 958 | "engines": { 959 | "node": ">=18.0.0" 960 | } 961 | }, 962 | "node_modules/eventsource-parser": { 963 | "version": "3.0.1", 964 | "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz", 965 | "integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==", 966 | "license": "MIT", 967 | "engines": { 968 | "node": ">=18.0.0" 969 | } 970 | }, 971 | "node_modules/express": { 972 | "version": "5.1.0", 973 | "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", 974 | "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", 975 | "license": "MIT", 976 | "dependencies": { 977 | "accepts": "^2.0.0", 978 | "body-parser": "^2.2.0", 979 | "content-disposition": "^1.0.0", 980 | "content-type": "^1.0.5", 981 | "cookie": "^0.7.1", 982 | "cookie-signature": "^1.2.1", 983 | "debug": "^4.4.0", 984 | "encodeurl": "^2.0.0", 985 | "escape-html": "^1.0.3", 986 | "etag": "^1.8.1", 987 | "finalhandler": "^2.1.0", 988 | "fresh": "^2.0.0", 989 | "http-errors": "^2.0.0", 990 | "merge-descriptors": "^2.0.0", 991 | "mime-types": "^3.0.0", 992 | "on-finished": "^2.4.1", 993 | "once": "^1.4.0", 994 | "parseurl": "^1.3.3", 995 | "proxy-addr": "^2.0.7", 996 | "qs": "^6.14.0", 997 | "range-parser": "^1.2.1", 998 | "router": "^2.2.0", 999 | "send": "^1.1.0", 1000 | "serve-static": "^2.2.0", 1001 | "statuses": "^2.0.1", 1002 | "type-is": "^2.0.1", 1003 | "vary": "^1.1.2" 1004 | }, 1005 | "engines": { 1006 | "node": ">= 18" 1007 | }, 1008 | "funding": { 1009 | "type": "opencollective", 1010 | "url": "https://opencollective.com/express" 1011 | } 1012 | }, 1013 | "node_modules/express-rate-limit": { 1014 | "version": "7.5.0", 1015 | "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", 1016 | "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", 1017 | "license": "MIT", 1018 | "engines": { 1019 | "node": ">= 16" 1020 | }, 1021 | "funding": { 1022 | "url": "https://github.com/sponsors/express-rate-limit" 1023 | }, 1024 | "peerDependencies": { 1025 | "express": "^4.11 || 5 || ^5.0.0-beta.1" 1026 | } 1027 | }, 1028 | "node_modules/finalhandler": { 1029 | "version": "2.1.0", 1030 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", 1031 | "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", 1032 | "license": "MIT", 1033 | "dependencies": { 1034 | "debug": "^4.4.0", 1035 | "encodeurl": "^2.0.0", 1036 | "escape-html": "^1.0.3", 1037 | "on-finished": "^2.4.1", 1038 | "parseurl": "^1.3.3", 1039 | "statuses": "^2.0.1" 1040 | }, 1041 | "engines": { 1042 | "node": ">= 0.8" 1043 | } 1044 | }, 1045 | "node_modules/forwarded": { 1046 | "version": "0.2.0", 1047 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 1048 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 1049 | "license": "MIT", 1050 | "engines": { 1051 | "node": ">= 0.6" 1052 | } 1053 | }, 1054 | "node_modules/fresh": { 1055 | "version": "2.0.0", 1056 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", 1057 | "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", 1058 | "license": "MIT", 1059 | "engines": { 1060 | "node": ">= 0.8" 1061 | } 1062 | }, 1063 | "node_modules/function-bind": { 1064 | "version": "1.1.2", 1065 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 1066 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 1067 | "license": "MIT", 1068 | "funding": { 1069 | "url": "https://github.com/sponsors/ljharb" 1070 | } 1071 | }, 1072 | "node_modules/get-intrinsic": { 1073 | "version": "1.3.0", 1074 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", 1075 | "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", 1076 | "license": "MIT", 1077 | "dependencies": { 1078 | "call-bind-apply-helpers": "^1.0.2", 1079 | "es-define-property": "^1.0.1", 1080 | "es-errors": "^1.3.0", 1081 | "es-object-atoms": "^1.1.1", 1082 | "function-bind": "^1.1.2", 1083 | "get-proto": "^1.0.1", 1084 | "gopd": "^1.2.0", 1085 | "has-symbols": "^1.1.0", 1086 | "hasown": "^2.0.2", 1087 | "math-intrinsics": "^1.1.0" 1088 | }, 1089 | "engines": { 1090 | "node": ">= 0.4" 1091 | }, 1092 | "funding": { 1093 | "url": "https://github.com/sponsors/ljharb" 1094 | } 1095 | }, 1096 | "node_modules/get-proto": { 1097 | "version": "1.0.1", 1098 | "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", 1099 | "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", 1100 | "license": "MIT", 1101 | "dependencies": { 1102 | "dunder-proto": "^1.0.1", 1103 | "es-object-atoms": "^1.0.0" 1104 | }, 1105 | "engines": { 1106 | "node": ">= 0.4" 1107 | } 1108 | }, 1109 | "node_modules/gopd": { 1110 | "version": "1.2.0", 1111 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 1112 | "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 1113 | "license": "MIT", 1114 | "engines": { 1115 | "node": ">= 0.4" 1116 | }, 1117 | "funding": { 1118 | "url": "https://github.com/sponsors/ljharb" 1119 | } 1120 | }, 1121 | "node_modules/has-symbols": { 1122 | "version": "1.1.0", 1123 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 1124 | "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 1125 | "license": "MIT", 1126 | "engines": { 1127 | "node": ">= 0.4" 1128 | }, 1129 | "funding": { 1130 | "url": "https://github.com/sponsors/ljharb" 1131 | } 1132 | }, 1133 | "node_modules/hasown": { 1134 | "version": "2.0.2", 1135 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 1136 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 1137 | "license": "MIT", 1138 | "dependencies": { 1139 | "function-bind": "^1.1.2" 1140 | }, 1141 | "engines": { 1142 | "node": ">= 0.4" 1143 | } 1144 | }, 1145 | "node_modules/http-errors": { 1146 | "version": "2.0.0", 1147 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 1148 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 1149 | "license": "MIT", 1150 | "dependencies": { 1151 | "depd": "2.0.0", 1152 | "inherits": "2.0.4", 1153 | "setprototypeof": "1.2.0", 1154 | "statuses": "2.0.1", 1155 | "toidentifier": "1.0.1" 1156 | }, 1157 | "engines": { 1158 | "node": ">= 0.8" 1159 | } 1160 | }, 1161 | "node_modules/iconv-lite": { 1162 | "version": "0.6.3", 1163 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 1164 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 1165 | "license": "MIT", 1166 | "dependencies": { 1167 | "safer-buffer": ">= 2.1.2 < 3.0.0" 1168 | }, 1169 | "engines": { 1170 | "node": ">=0.10.0" 1171 | } 1172 | }, 1173 | "node_modules/inherits": { 1174 | "version": "2.0.4", 1175 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1176 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1177 | "license": "ISC" 1178 | }, 1179 | "node_modules/ipaddr.js": { 1180 | "version": "1.9.1", 1181 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 1182 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 1183 | "license": "MIT", 1184 | "engines": { 1185 | "node": ">= 0.10" 1186 | } 1187 | }, 1188 | "node_modules/is-promise": { 1189 | "version": "4.0.0", 1190 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", 1191 | "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", 1192 | "license": "MIT" 1193 | }, 1194 | "node_modules/isexe": { 1195 | "version": "2.0.0", 1196 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1197 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 1198 | "license": "ISC" 1199 | }, 1200 | "node_modules/make-error": { 1201 | "version": "1.3.6", 1202 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", 1203 | "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", 1204 | "dev": true, 1205 | "license": "ISC" 1206 | }, 1207 | "node_modules/math-intrinsics": { 1208 | "version": "1.1.0", 1209 | "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 1210 | "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 1211 | "license": "MIT", 1212 | "engines": { 1213 | "node": ">= 0.4" 1214 | } 1215 | }, 1216 | "node_modules/media-typer": { 1217 | "version": "1.1.0", 1218 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", 1219 | "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", 1220 | "license": "MIT", 1221 | "engines": { 1222 | "node": ">= 0.8" 1223 | } 1224 | }, 1225 | "node_modules/merge-descriptors": { 1226 | "version": "2.0.0", 1227 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", 1228 | "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", 1229 | "license": "MIT", 1230 | "engines": { 1231 | "node": ">=18" 1232 | }, 1233 | "funding": { 1234 | "url": "https://github.com/sponsors/sindresorhus" 1235 | } 1236 | }, 1237 | "node_modules/mime-db": { 1238 | "version": "1.54.0", 1239 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", 1240 | "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", 1241 | "license": "MIT", 1242 | "engines": { 1243 | "node": ">= 0.6" 1244 | } 1245 | }, 1246 | "node_modules/mime-types": { 1247 | "version": "3.0.1", 1248 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", 1249 | "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", 1250 | "license": "MIT", 1251 | "dependencies": { 1252 | "mime-db": "^1.54.0" 1253 | }, 1254 | "engines": { 1255 | "node": ">= 0.6" 1256 | } 1257 | }, 1258 | "node_modules/ms": { 1259 | "version": "2.1.3", 1260 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1261 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1262 | "license": "MIT" 1263 | }, 1264 | "node_modules/negotiator": { 1265 | "version": "1.0.0", 1266 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", 1267 | "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", 1268 | "license": "MIT", 1269 | "engines": { 1270 | "node": ">= 0.6" 1271 | } 1272 | }, 1273 | "node_modules/object-assign": { 1274 | "version": "4.1.1", 1275 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1276 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 1277 | "license": "MIT", 1278 | "engines": { 1279 | "node": ">=0.10.0" 1280 | } 1281 | }, 1282 | "node_modules/object-inspect": { 1283 | "version": "1.13.4", 1284 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", 1285 | "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", 1286 | "license": "MIT", 1287 | "engines": { 1288 | "node": ">= 0.4" 1289 | }, 1290 | "funding": { 1291 | "url": "https://github.com/sponsors/ljharb" 1292 | } 1293 | }, 1294 | "node_modules/on-finished": { 1295 | "version": "2.4.1", 1296 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 1297 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 1298 | "license": "MIT", 1299 | "dependencies": { 1300 | "ee-first": "1.1.1" 1301 | }, 1302 | "engines": { 1303 | "node": ">= 0.8" 1304 | } 1305 | }, 1306 | "node_modules/once": { 1307 | "version": "1.4.0", 1308 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1309 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1310 | "license": "ISC", 1311 | "dependencies": { 1312 | "wrappy": "1" 1313 | } 1314 | }, 1315 | "node_modules/parseurl": { 1316 | "version": "1.3.3", 1317 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1318 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 1319 | "license": "MIT", 1320 | "engines": { 1321 | "node": ">= 0.8" 1322 | } 1323 | }, 1324 | "node_modules/path-key": { 1325 | "version": "3.1.1", 1326 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1327 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1328 | "license": "MIT", 1329 | "engines": { 1330 | "node": ">=8" 1331 | } 1332 | }, 1333 | "node_modules/path-to-regexp": { 1334 | "version": "8.2.0", 1335 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", 1336 | "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", 1337 | "license": "MIT", 1338 | "engines": { 1339 | "node": ">=16" 1340 | } 1341 | }, 1342 | "node_modules/pkce-challenge": { 1343 | "version": "5.0.0", 1344 | "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", 1345 | "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", 1346 | "license": "MIT", 1347 | "engines": { 1348 | "node": ">=16.20.0" 1349 | } 1350 | }, 1351 | "node_modules/proxy-addr": { 1352 | "version": "2.0.7", 1353 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1354 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1355 | "license": "MIT", 1356 | "dependencies": { 1357 | "forwarded": "0.2.0", 1358 | "ipaddr.js": "1.9.1" 1359 | }, 1360 | "engines": { 1361 | "node": ">= 0.10" 1362 | } 1363 | }, 1364 | "node_modules/qs": { 1365 | "version": "6.14.0", 1366 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", 1367 | "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", 1368 | "license": "BSD-3-Clause", 1369 | "dependencies": { 1370 | "side-channel": "^1.1.0" 1371 | }, 1372 | "engines": { 1373 | "node": ">=0.6" 1374 | }, 1375 | "funding": { 1376 | "url": "https://github.com/sponsors/ljharb" 1377 | } 1378 | }, 1379 | "node_modules/range-parser": { 1380 | "version": "1.2.1", 1381 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1382 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 1383 | "license": "MIT", 1384 | "engines": { 1385 | "node": ">= 0.6" 1386 | } 1387 | }, 1388 | "node_modules/raw-body": { 1389 | "version": "3.0.0", 1390 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", 1391 | "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", 1392 | "license": "MIT", 1393 | "dependencies": { 1394 | "bytes": "3.1.2", 1395 | "http-errors": "2.0.0", 1396 | "iconv-lite": "0.6.3", 1397 | "unpipe": "1.0.0" 1398 | }, 1399 | "engines": { 1400 | "node": ">= 0.8" 1401 | } 1402 | }, 1403 | "node_modules/router": { 1404 | "version": "2.2.0", 1405 | "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", 1406 | "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", 1407 | "license": "MIT", 1408 | "dependencies": { 1409 | "debug": "^4.4.0", 1410 | "depd": "^2.0.0", 1411 | "is-promise": "^4.0.0", 1412 | "parseurl": "^1.3.3", 1413 | "path-to-regexp": "^8.0.0" 1414 | }, 1415 | "engines": { 1416 | "node": ">= 18" 1417 | } 1418 | }, 1419 | "node_modules/safe-buffer": { 1420 | "version": "5.2.1", 1421 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1422 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1423 | "funding": [ 1424 | { 1425 | "type": "github", 1426 | "url": "https://github.com/sponsors/feross" 1427 | }, 1428 | { 1429 | "type": "patreon", 1430 | "url": "https://www.patreon.com/feross" 1431 | }, 1432 | { 1433 | "type": "consulting", 1434 | "url": "https://feross.org/support" 1435 | } 1436 | ], 1437 | "license": "MIT" 1438 | }, 1439 | "node_modules/safer-buffer": { 1440 | "version": "2.1.2", 1441 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1442 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1443 | "license": "MIT" 1444 | }, 1445 | "node_modules/send": { 1446 | "version": "1.2.0", 1447 | "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", 1448 | "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", 1449 | "license": "MIT", 1450 | "dependencies": { 1451 | "debug": "^4.3.5", 1452 | "encodeurl": "^2.0.0", 1453 | "escape-html": "^1.0.3", 1454 | "etag": "^1.8.1", 1455 | "fresh": "^2.0.0", 1456 | "http-errors": "^2.0.0", 1457 | "mime-types": "^3.0.1", 1458 | "ms": "^2.1.3", 1459 | "on-finished": "^2.4.1", 1460 | "range-parser": "^1.2.1", 1461 | "statuses": "^2.0.1" 1462 | }, 1463 | "engines": { 1464 | "node": ">= 18" 1465 | } 1466 | }, 1467 | "node_modules/serve-static": { 1468 | "version": "2.2.0", 1469 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", 1470 | "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", 1471 | "license": "MIT", 1472 | "dependencies": { 1473 | "encodeurl": "^2.0.0", 1474 | "escape-html": "^1.0.3", 1475 | "parseurl": "^1.3.3", 1476 | "send": "^1.2.0" 1477 | }, 1478 | "engines": { 1479 | "node": ">= 18" 1480 | } 1481 | }, 1482 | "node_modules/setprototypeof": { 1483 | "version": "1.2.0", 1484 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1485 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", 1486 | "license": "ISC" 1487 | }, 1488 | "node_modules/shebang-command": { 1489 | "version": "2.0.0", 1490 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1491 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1492 | "license": "MIT", 1493 | "dependencies": { 1494 | "shebang-regex": "^3.0.0" 1495 | }, 1496 | "engines": { 1497 | "node": ">=8" 1498 | } 1499 | }, 1500 | "node_modules/shebang-regex": { 1501 | "version": "3.0.0", 1502 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1503 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1504 | "license": "MIT", 1505 | "engines": { 1506 | "node": ">=8" 1507 | } 1508 | }, 1509 | "node_modules/side-channel": { 1510 | "version": "1.1.0", 1511 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", 1512 | "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", 1513 | "license": "MIT", 1514 | "dependencies": { 1515 | "es-errors": "^1.3.0", 1516 | "object-inspect": "^1.13.3", 1517 | "side-channel-list": "^1.0.0", 1518 | "side-channel-map": "^1.0.1", 1519 | "side-channel-weakmap": "^1.0.2" 1520 | }, 1521 | "engines": { 1522 | "node": ">= 0.4" 1523 | }, 1524 | "funding": { 1525 | "url": "https://github.com/sponsors/ljharb" 1526 | } 1527 | }, 1528 | "node_modules/side-channel-list": { 1529 | "version": "1.0.0", 1530 | "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", 1531 | "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", 1532 | "license": "MIT", 1533 | "dependencies": { 1534 | "es-errors": "^1.3.0", 1535 | "object-inspect": "^1.13.3" 1536 | }, 1537 | "engines": { 1538 | "node": ">= 0.4" 1539 | }, 1540 | "funding": { 1541 | "url": "https://github.com/sponsors/ljharb" 1542 | } 1543 | }, 1544 | "node_modules/side-channel-map": { 1545 | "version": "1.0.1", 1546 | "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", 1547 | "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", 1548 | "license": "MIT", 1549 | "dependencies": { 1550 | "call-bound": "^1.0.2", 1551 | "es-errors": "^1.3.0", 1552 | "get-intrinsic": "^1.2.5", 1553 | "object-inspect": "^1.13.3" 1554 | }, 1555 | "engines": { 1556 | "node": ">= 0.4" 1557 | }, 1558 | "funding": { 1559 | "url": "https://github.com/sponsors/ljharb" 1560 | } 1561 | }, 1562 | "node_modules/side-channel-weakmap": { 1563 | "version": "1.0.2", 1564 | "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", 1565 | "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", 1566 | "license": "MIT", 1567 | "dependencies": { 1568 | "call-bound": "^1.0.2", 1569 | "es-errors": "^1.3.0", 1570 | "get-intrinsic": "^1.2.5", 1571 | "object-inspect": "^1.13.3", 1572 | "side-channel-map": "^1.0.1" 1573 | }, 1574 | "engines": { 1575 | "node": ">= 0.4" 1576 | }, 1577 | "funding": { 1578 | "url": "https://github.com/sponsors/ljharb" 1579 | } 1580 | }, 1581 | "node_modules/statuses": { 1582 | "version": "2.0.1", 1583 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 1584 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 1585 | "license": "MIT", 1586 | "engines": { 1587 | "node": ">= 0.8" 1588 | } 1589 | }, 1590 | "node_modules/toidentifier": { 1591 | "version": "1.0.1", 1592 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1593 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 1594 | "license": "MIT", 1595 | "engines": { 1596 | "node": ">=0.6" 1597 | } 1598 | }, 1599 | "node_modules/ts-node": { 1600 | "version": "10.9.2", 1601 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", 1602 | "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", 1603 | "dev": true, 1604 | "license": "MIT", 1605 | "dependencies": { 1606 | "@cspotcode/source-map-support": "^0.8.0", 1607 | "@tsconfig/node10": "^1.0.7", 1608 | "@tsconfig/node12": "^1.0.7", 1609 | "@tsconfig/node14": "^1.0.0", 1610 | "@tsconfig/node16": "^1.0.2", 1611 | "acorn": "^8.4.1", 1612 | "acorn-walk": "^8.1.1", 1613 | "arg": "^4.1.0", 1614 | "create-require": "^1.1.0", 1615 | "diff": "^4.0.1", 1616 | "make-error": "^1.1.1", 1617 | "v8-compile-cache-lib": "^3.0.1", 1618 | "yn": "3.1.1" 1619 | }, 1620 | "bin": { 1621 | "ts-node": "dist/bin.js", 1622 | "ts-node-cwd": "dist/bin-cwd.js", 1623 | "ts-node-esm": "dist/bin-esm.js", 1624 | "ts-node-script": "dist/bin-script.js", 1625 | "ts-node-transpile-only": "dist/bin-transpile.js", 1626 | "ts-script": "dist/bin-script-deprecated.js" 1627 | }, 1628 | "peerDependencies": { 1629 | "@swc/core": ">=1.2.50", 1630 | "@swc/wasm": ">=1.2.50", 1631 | "@types/node": "*", 1632 | "typescript": ">=2.7" 1633 | }, 1634 | "peerDependenciesMeta": { 1635 | "@swc/core": { 1636 | "optional": true 1637 | }, 1638 | "@swc/wasm": { 1639 | "optional": true 1640 | } 1641 | } 1642 | }, 1643 | "node_modules/type-is": { 1644 | "version": "2.0.1", 1645 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", 1646 | "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", 1647 | "license": "MIT", 1648 | "dependencies": { 1649 | "content-type": "^1.0.5", 1650 | "media-typer": "^1.1.0", 1651 | "mime-types": "^3.0.0" 1652 | }, 1653 | "engines": { 1654 | "node": ">= 0.6" 1655 | } 1656 | }, 1657 | "node_modules/typescript": { 1658 | "version": "5.8.3", 1659 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", 1660 | "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", 1661 | "dev": true, 1662 | "license": "Apache-2.0", 1663 | "bin": { 1664 | "tsc": "bin/tsc", 1665 | "tsserver": "bin/tsserver" 1666 | }, 1667 | "engines": { 1668 | "node": ">=14.17" 1669 | } 1670 | }, 1671 | "node_modules/undici-types": { 1672 | "version": "6.19.8", 1673 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", 1674 | "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", 1675 | "dev": true, 1676 | "license": "MIT" 1677 | }, 1678 | "node_modules/unpipe": { 1679 | "version": "1.0.0", 1680 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1681 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 1682 | "license": "MIT", 1683 | "engines": { 1684 | "node": ">= 0.8" 1685 | } 1686 | }, 1687 | "node_modules/v8-compile-cache-lib": { 1688 | "version": "3.0.1", 1689 | "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", 1690 | "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", 1691 | "dev": true, 1692 | "license": "MIT" 1693 | }, 1694 | "node_modules/vary": { 1695 | "version": "1.1.2", 1696 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1697 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 1698 | "license": "MIT", 1699 | "engines": { 1700 | "node": ">= 0.8" 1701 | } 1702 | }, 1703 | "node_modules/which": { 1704 | "version": "2.0.2", 1705 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1706 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1707 | "license": "ISC", 1708 | "dependencies": { 1709 | "isexe": "^2.0.0" 1710 | }, 1711 | "bin": { 1712 | "node-which": "bin/node-which" 1713 | }, 1714 | "engines": { 1715 | "node": ">= 8" 1716 | } 1717 | }, 1718 | "node_modules/wrappy": { 1719 | "version": "1.0.2", 1720 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1721 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 1722 | "license": "ISC" 1723 | }, 1724 | "node_modules/yn": { 1725 | "version": "3.1.1", 1726 | "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", 1727 | "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", 1728 | "dev": true, 1729 | "license": "MIT", 1730 | "engines": { 1731 | "node": ">=6" 1732 | } 1733 | }, 1734 | "node_modules/zod": { 1735 | "version": "3.24.2", 1736 | "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.2.tgz", 1737 | "integrity": "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==", 1738 | "license": "MIT", 1739 | "funding": { 1740 | "url": "https://github.com/sponsors/colinhacks" 1741 | } 1742 | }, 1743 | "node_modules/zod-to-json-schema": { 1744 | "version": "3.24.5", 1745 | "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz", 1746 | "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==", 1747 | "license": "ISC", 1748 | "peerDependencies": { 1749 | "zod": "^3.24.1" 1750 | } 1751 | } 1752 | } 1753 | } 1754 | -------------------------------------------------------------------------------- /mcp-function/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mcp-streamablehttp-lambda", 3 | "version": "1.0.0", 4 | "description": "Sample implementation of MCP Streamable HTTP protocol", 5 | "type": "commonjs", 6 | "main": "dist/server.js", 7 | "scripts": { 8 | "build": "tsc", 9 | "start:server": "node dist/server.js", 10 | "start:client": "node dist/client.js", 11 | "dev:server": "ts-node src/server.ts", 12 | "dev:client": "ts-node src/client.ts", 13 | "test": "echo \"Error: no test specified\" && exit 1" 14 | }, 15 | "keywords": [ 16 | "mcp", 17 | "streamable-http", 18 | "typescript" 19 | ], 20 | "author": "", 21 | "license": "MIT", 22 | "dependencies": { 23 | "@modelcontextprotocol/sdk": "^1.10.1", 24 | "body-parser": "^2.2.0", 25 | "esbuild": "^0.25.2", 26 | "express": "^5.1.0", 27 | "zod": "^3.22.4", 28 | "zod-to-json-schema": "^3.22.3" 29 | }, 30 | "devDependencies": { 31 | "@types/express": "^5.0.1", 32 | "@types/node": "^20.11.30", 33 | "ts-node": "^10.9.2", 34 | "typescript": "^5.4.5" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /mcp-function/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | node output/bundle.js 4 | -------------------------------------------------------------------------------- /mcp-function/src/client.ts: -------------------------------------------------------------------------------- 1 | import { Client } from '@modelcontextprotocol/sdk/client/index.js'; 2 | import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; 3 | import { createInterface } from 'node:readline'; 4 | import { 5 | ListToolsRequest, 6 | ListToolsResultSchema, 7 | CallToolRequest, 8 | CallToolResultSchema, 9 | ListPromptsRequest, 10 | ListPromptsResultSchema, 11 | GetPromptRequest, 12 | GetPromptResultSchema, 13 | ListResourcesRequest, 14 | ListResourcesResultSchema, 15 | LoggingMessageNotificationSchema, 16 | ResourceListChangedNotificationSchema, 17 | } from '@modelcontextprotocol/sdk/types.js'; 18 | 19 | // Create readline interface for user input 20 | const readline = createInterface({ 21 | input: process.stdin, 22 | output: process.stdout 23 | }); 24 | 25 | // Track received notifications for debugging resumability 26 | let notificationCount = 0; 27 | 28 | // Global client and transport for interactive commands 29 | let client: Client | null = null; 30 | let transport: StreamableHTTPClientTransport | null = null; 31 | let serverUrl = 'http://localhost:3000/mcp'; 32 | let notificationsToolLastEventId: string | undefined = undefined; 33 | let sessionId: string | undefined = undefined; 34 | 35 | async function main(): Promise { 36 | console.log('MCP Interactive Client'); 37 | console.log('====================='); 38 | 39 | // Connect to server immediately with default settings 40 | await connect(); 41 | 42 | // Print help and start the command loop 43 | printHelp(); 44 | commandLoop(); 45 | } 46 | 47 | function printHelp(): void { 48 | console.log('\nAvailable commands:'); 49 | console.log(' connect [url] - Connect to MCP server (default: http://localhost:3000/mcp)'); 50 | console.log(' disconnect - Disconnect from server'); 51 | console.log(' terminate-session - Terminate the current session'); 52 | console.log(' reconnect - Reconnect to the server'); 53 | console.log(' list-tools - List available tools'); 54 | console.log(' call-tool [args] - Call a tool with optional JSON arguments'); 55 | console.log(' greet [name] - Call the greet tool'); 56 | console.log(' multi-greet [name] - Call the multi-greet tool with notifications'); 57 | console.log(' start-notifications [interval] [count] - Start periodic notifications'); 58 | console.log(' list-prompts - List available prompts'); 59 | console.log(' get-prompt [name] [args] - Get a prompt with optional JSON arguments'); 60 | console.log(' list-resources - List available resources'); 61 | console.log(' help - Show this help'); 62 | console.log(' quit - Exit the program'); 63 | } 64 | 65 | function commandLoop(): void { 66 | readline.question('\n> ', async (input) => { 67 | const args = input.trim().split(/\s+/); 68 | const command = args[0]?.toLowerCase(); 69 | 70 | try { 71 | switch (command) { 72 | case 'connect': 73 | await connect(args[1]); 74 | break; 75 | 76 | case 'disconnect': 77 | await disconnect(); 78 | break; 79 | 80 | case 'terminate-session': 81 | await terminateSession(); 82 | break; 83 | 84 | case 'reconnect': 85 | await reconnect(); 86 | break; 87 | 88 | case 'list-tools': 89 | await listTools(); 90 | break; 91 | 92 | case 'call-tool': 93 | if (args.length < 2) { 94 | console.log('Usage: call-tool [args]'); 95 | } else { 96 | const toolName = args[1]; 97 | let toolArgs = {}; 98 | if (args.length > 2) { 99 | try { 100 | toolArgs = JSON.parse(args.slice(2).join(' ')); 101 | } catch { 102 | console.log('Invalid JSON arguments. Using empty args.'); 103 | } 104 | } 105 | await callTool(toolName, toolArgs); 106 | } 107 | break; 108 | 109 | case 'greet': 110 | await callGreetTool(args[1] || 'MCP User'); 111 | break; 112 | 113 | case 'multi-greet': 114 | await callMultiGreetTool(args[1] || 'MCP User'); 115 | break; 116 | 117 | case 'start-notifications': { 118 | const interval = args[1] ? parseInt(args[1], 10) : 2000; 119 | const count = args[2] ? parseInt(args[2], 10) : 10; 120 | await startNotifications(interval, count); 121 | break; 122 | } 123 | 124 | case 'list-prompts': 125 | await listPrompts(); 126 | break; 127 | 128 | case 'get-prompt': 129 | if (args.length < 2) { 130 | console.log('Usage: get-prompt [args]'); 131 | } else { 132 | const promptName = args[1]; 133 | let promptArgs = {}; 134 | if (args.length > 2) { 135 | try { 136 | promptArgs = JSON.parse(args.slice(2).join(' ')); 137 | } catch { 138 | console.log('Invalid JSON arguments. Using empty args.'); 139 | } 140 | } 141 | await getPrompt(promptName, promptArgs); 142 | } 143 | break; 144 | 145 | case 'list-resources': 146 | await listResources(); 147 | break; 148 | 149 | case 'help': 150 | printHelp(); 151 | break; 152 | 153 | case 'quit': 154 | case 'exit': 155 | await cleanup(); 156 | return; 157 | 158 | default: 159 | if (command) { 160 | console.log(`Unknown command: ${command}`); 161 | } 162 | break; 163 | } 164 | } catch (error) { 165 | console.error(`Error executing command: ${error}`); 166 | } 167 | 168 | // Continue the command loop 169 | commandLoop(); 170 | }); 171 | } 172 | 173 | async function connect(url?: string): Promise { 174 | if (client) { 175 | console.log('Already connected. Disconnect first.'); 176 | return; 177 | } 178 | 179 | if (url) { 180 | serverUrl = url; 181 | } 182 | 183 | console.log(`Connecting to ${serverUrl}...`); 184 | 185 | try { 186 | // Create a new client 187 | client = new Client({ 188 | name: 'example-client', 189 | version: '1.0.0' 190 | }); 191 | client.onerror = (error) => { 192 | console.error('\x1b[31mClient error:', error, '\x1b[0m'); 193 | } 194 | 195 | transport = new StreamableHTTPClientTransport( 196 | new URL(serverUrl), 197 | { 198 | sessionId: sessionId 199 | } 200 | ); 201 | 202 | // Set up notification handlers 203 | client.setNotificationHandler(LoggingMessageNotificationSchema, (notification) => { 204 | notificationCount++; 205 | console.log(`\nNotification #${notificationCount}: ${notification.params.level} - ${notification.params.data}`); 206 | // Re-display the prompt 207 | process.stdout.write('> '); 208 | }); 209 | 210 | client.setNotificationHandler(ResourceListChangedNotificationSchema, async (_) => { 211 | console.log(`\nResource list changed notification received!`); 212 | try { 213 | if (!client) { 214 | console.log('Client disconnected, cannot fetch resources'); 215 | return; 216 | } 217 | const resourcesResult = await client.request({ 218 | method: 'resources/list', 219 | params: {} 220 | }, ListResourcesResultSchema); 221 | console.log('Available resources count:', resourcesResult.resources.length); 222 | } catch { 223 | console.log('Failed to list resources after change notification'); 224 | } 225 | // Re-display the prompt 226 | process.stdout.write('> '); 227 | }); 228 | 229 | // Connect the client 230 | await client.connect(transport); 231 | sessionId = transport.sessionId 232 | console.log('Transport created with session ID:', sessionId); 233 | console.log('Connected to MCP server'); 234 | } catch (error) { 235 | console.error('Failed to connect:', error); 236 | client = null; 237 | transport = null; 238 | } 239 | } 240 | 241 | async function disconnect(): Promise { 242 | if (!client || !transport) { 243 | console.log('Not connected.'); 244 | return; 245 | } 246 | 247 | try { 248 | await transport.close(); 249 | console.log('Disconnected from MCP server'); 250 | client = null; 251 | transport = null; 252 | } catch (error) { 253 | console.error('Error disconnecting:', error); 254 | } 255 | } 256 | 257 | async function terminateSession(): Promise { 258 | if (!client || !transport) { 259 | console.log('Not connected.'); 260 | return; 261 | } 262 | 263 | try { 264 | console.log('Terminating session with ID:', transport.sessionId); 265 | await transport.terminateSession(); 266 | console.log('Session terminated successfully'); 267 | 268 | // Check if sessionId was cleared after termination 269 | if (!transport.sessionId) { 270 | console.log('Session ID has been cleared'); 271 | sessionId = undefined; 272 | 273 | // Also close the transport and clear client objects 274 | await transport.close(); 275 | console.log('Transport closed after session termination'); 276 | client = null; 277 | transport = null; 278 | } else { 279 | console.log('Server responded with 405 Method Not Allowed (session termination not supported)'); 280 | console.log('Session ID is still active:', transport.sessionId); 281 | } 282 | } catch (error) { 283 | console.error('Error terminating session:', error); 284 | } 285 | } 286 | 287 | async function reconnect(): Promise { 288 | if (client) { 289 | await disconnect(); 290 | } 291 | await connect(); 292 | } 293 | 294 | async function listTools(): Promise { 295 | if (!client) { 296 | console.log('Not connected to server.'); 297 | return; 298 | } 299 | 300 | try { 301 | const toolsRequest: ListToolsRequest = { 302 | method: 'tools/list', 303 | params: {} 304 | }; 305 | const toolsResult = await client.request(toolsRequest, ListToolsResultSchema); 306 | 307 | console.log('Available tools:'); 308 | if (toolsResult.tools.length === 0) { 309 | console.log(' No tools available'); 310 | } else { 311 | for (const tool of toolsResult.tools) { 312 | console.log(` - ${tool.name}: ${tool.description}`); 313 | } 314 | } 315 | } catch (error) { 316 | console.log(`Tools not supported by this server (${error})`); 317 | } 318 | } 319 | 320 | async function callTool(name: string, args: Record): Promise { 321 | if (!client) { 322 | console.log('Not connected to server.'); 323 | return; 324 | } 325 | 326 | try { 327 | const request: CallToolRequest = { 328 | method: 'tools/call', 329 | params: { 330 | name, 331 | arguments: args 332 | } 333 | }; 334 | 335 | console.log(`Calling tool '${name}' with args:`, args); 336 | const onLastEventIdUpdate = (event: string) => { 337 | notificationsToolLastEventId = event; 338 | }; 339 | const result = await client.request(request, CallToolResultSchema, { 340 | resumptionToken: notificationsToolLastEventId, onresumptiontoken: onLastEventIdUpdate 341 | }); 342 | 343 | console.log('Tool result:'); 344 | result.content.forEach(item => { 345 | if (item.type === 'text') { 346 | console.log(` ${item.text}`); 347 | } else { 348 | console.log(` ${item.type} content:`, item); 349 | } 350 | }); 351 | } catch (error) { 352 | console.log(`Error calling tool ${name}: ${error}`); 353 | } 354 | } 355 | 356 | async function callGreetTool(name: string): Promise { 357 | await callTool('greet', { name }); 358 | } 359 | 360 | async function callMultiGreetTool(name: string): Promise { 361 | console.log('Calling multi-greet tool with notifications...'); 362 | await callTool('multi-greet', { name }); 363 | } 364 | 365 | async function startNotifications(interval: number, count: number): Promise { 366 | console.log(`Starting notification stream: interval=${interval}ms, count=${count || 'unlimited'}`); 367 | await callTool('start-notification-stream', { interval, count }); 368 | } 369 | 370 | async function listPrompts(): Promise { 371 | if (!client) { 372 | console.log('Not connected to server.'); 373 | return; 374 | } 375 | 376 | try { 377 | const promptsRequest: ListPromptsRequest = { 378 | method: 'prompts/list', 379 | params: {} 380 | }; 381 | const promptsResult = await client.request(promptsRequest, ListPromptsResultSchema); 382 | console.log('Available prompts:'); 383 | if (promptsResult.prompts.length === 0) { 384 | console.log(' No prompts available'); 385 | } else { 386 | for (const prompt of promptsResult.prompts) { 387 | console.log(` - ${prompt.name}: ${prompt.description}`); 388 | } 389 | } 390 | } catch (error) { 391 | console.log(`Prompts not supported by this server (${error})`); 392 | } 393 | } 394 | 395 | async function getPrompt(name: string, args: Record): Promise { 396 | if (!client) { 397 | console.log('Not connected to server.'); 398 | return; 399 | } 400 | 401 | try { 402 | const promptRequest: GetPromptRequest = { 403 | method: 'prompts/get', 404 | params: { 405 | name, 406 | arguments: args as Record 407 | } 408 | }; 409 | 410 | const promptResult = await client.request(promptRequest, GetPromptResultSchema); 411 | console.log('Prompt template:'); 412 | promptResult.messages.forEach((msg, index) => { 413 | console.log(` [${index + 1}] ${msg.role}: ${msg.content.text}`); 414 | }); 415 | } catch (error) { 416 | console.log(`Error getting prompt ${name}: ${error}`); 417 | } 418 | } 419 | 420 | async function listResources(): Promise { 421 | if (!client) { 422 | console.log('Not connected to server.'); 423 | return; 424 | } 425 | 426 | try { 427 | const resourcesRequest: ListResourcesRequest = { 428 | method: 'resources/list', 429 | params: {} 430 | }; 431 | const resourcesResult = await client.request(resourcesRequest, ListResourcesResultSchema); 432 | 433 | console.log('Available resources:'); 434 | if (resourcesResult.resources.length === 0) { 435 | console.log(' No resources available'); 436 | } else { 437 | for (const resource of resourcesResult.resources) { 438 | console.log(` - ${resource.name}: ${resource.uri}`); 439 | } 440 | } 441 | } catch (error) { 442 | console.log(`Resources not supported by this server (${error})`); 443 | } 444 | } 445 | 446 | async function cleanup(): Promise { 447 | if (client && transport) { 448 | try { 449 | // First try to terminate the session gracefully 450 | if (transport.sessionId) { 451 | try { 452 | console.log('Terminating session before exit...'); 453 | await transport.terminateSession(); 454 | console.log('Session terminated successfully'); 455 | } catch (error) { 456 | console.error('Error terminating session:', error); 457 | } 458 | } 459 | 460 | // Then close the transport 461 | await transport.close(); 462 | } catch (error) { 463 | console.error('Error closing transport:', error); 464 | } 465 | } 466 | 467 | process.stdin.setRawMode(false); 468 | readline.close(); 469 | console.log('\nGoodbye!'); 470 | process.exit(0); 471 | } 472 | 473 | // Set up raw mode for keyboard input to capture Escape key 474 | process.stdin.setRawMode(true); 475 | process.stdin.on('data', async (data) => { 476 | // Check for Escape key (27) 477 | if (data.length === 1 && data[0] === 27) { 478 | console.log('\nESC key pressed. Disconnecting from server...'); 479 | 480 | // Abort current operation and disconnect from server 481 | if (client && transport) { 482 | await disconnect(); 483 | console.log('Disconnected. Press Enter to continue.'); 484 | } else { 485 | console.log('Not connected to server.'); 486 | } 487 | 488 | // Re-display the prompt 489 | process.stdout.write('> '); 490 | } 491 | }); 492 | 493 | // Handle Ctrl+C 494 | process.on('SIGINT', async () => { 495 | console.log('\nReceived SIGINT. Cleaning up...'); 496 | await cleanup(); 497 | }); 498 | 499 | // Start the interactive client 500 | main().catch((error: unknown) => { 501 | console.error('Error running MCP client:', error); 502 | process.exit(1); 503 | }); -------------------------------------------------------------------------------- /mcp-function/src/server.ts: -------------------------------------------------------------------------------- 1 | import express, { Request, Response } from 'express'; 2 | import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; 3 | import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; 4 | import { z } from 'zod'; 5 | import { CallToolResult, GetPromptResult, ReadResourceResult } from '@modelcontextprotocol/sdk/types.js'; 6 | 7 | // Create an MCP server with implementation details 8 | const server = new McpServer({ 9 | name: 'stateless-streamable-http-server', 10 | version: '1.0.0', 11 | }, { capabilities: { logging: {} } }); 12 | 13 | // Register a simple prompt 14 | server.prompt( 15 | 'greeting-template', 16 | 'A simple greeting prompt template', 17 | { 18 | name: z.string().describe('Name to include in greeting'), 19 | }, 20 | async ({ name }): Promise => { 21 | return { 22 | messages: [ 23 | { 24 | role: 'user', 25 | content: { 26 | type: 'text', 27 | text: `Please greet ${name} in a friendly manner.`, 28 | }, 29 | }, 30 | ], 31 | }; 32 | } 33 | ); 34 | 35 | // Register a simple tool that returns a greeting 36 | server.tool( 37 | 'greet', 38 | 'A simple greeting tool', 39 | { 40 | name: z.string().describe('Name to greet'), 41 | }, 42 | async ({ name }): Promise => { 43 | return { 44 | content: [ 45 | { 46 | type: 'text', 47 | text: `Hello, ${name}!`, 48 | }, 49 | ], 50 | }; 51 | } 52 | ); 53 | 54 | // Register a tool that sends multiple greetings with notifications 55 | server.tool( 56 | 'multi-greet', 57 | 'A tool that sends different greetings with delays between them', 58 | { 59 | name: z.string().describe('Name to greet'), 60 | }, 61 | async ({ name }, { sendNotification }): Promise => { 62 | const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); 63 | 64 | await sendNotification({ 65 | method: "notifications/message", 66 | params: { level: "debug", data: `Starting multi-greet for ${name}` } 67 | }); 68 | 69 | await sleep(1000); // Wait 1 second before first greeting 70 | 71 | await sendNotification({ 72 | method: "notifications/message", 73 | params: { level: "info", data: `Sending first greeting to ${name}` } 74 | }); 75 | 76 | await sleep(1000); // Wait another second before second greeting 77 | 78 | await sendNotification({ 79 | method: "notifications/message", 80 | params: { level: "info", data: `Sending second greeting to ${name}` } 81 | }); 82 | 83 | return { 84 | content: [ 85 | { 86 | type: 'text', 87 | text: `Good morning, ${name}!`, 88 | } 89 | ], 90 | }; 91 | } 92 | ); 93 | 94 | // Create a simple resource at a fixed URI 95 | server.resource( 96 | 'greeting-resource', 97 | 'https://example.com/greetings/default', 98 | { mimeType: 'text/plain' }, 99 | async (): Promise => { 100 | return { 101 | contents: [ 102 | { 103 | uri: 'https://example.com/greetings/default', 104 | text: 'Hello, world!', 105 | }, 106 | ], 107 | }; 108 | } 109 | ); 110 | 111 | const app = express(); 112 | app.use(express.json()); 113 | 114 | const transport: StreamableHTTPServerTransport = new StreamableHTTPServerTransport({ 115 | sessionIdGenerator: undefined, 116 | }); 117 | 118 | // Setup routes for the server 119 | const setupServer = async () => { 120 | await server.connect(transport); 121 | }; 122 | 123 | app.post('/mcp', async (req: Request, res: Response) => { 124 | console.log('Received MCP request:', req.body); 125 | try { 126 | await transport.handleRequest(req, res, req.body); 127 | } catch (error) { 128 | console.error('Error handling MCP request:', error); 129 | if (!res.headersSent) { 130 | res.status(500).json({ 131 | jsonrpc: '2.0', 132 | error: { 133 | code: -32603, 134 | message: 'Internal server error', 135 | }, 136 | id: null, 137 | }); 138 | } 139 | } 140 | }); 141 | 142 | app.get('/mcp', async (req: Request, res: Response) => { 143 | console.log('Received GET MCP request'); 144 | res.writeHead(405).end(JSON.stringify({ 145 | jsonrpc: "2.0", 146 | error: { 147 | code: -32000, 148 | message: "Method not allowed." 149 | }, 150 | id: null 151 | })); 152 | }); 153 | 154 | app.delete('/mcp', async (req: Request, res: Response) => { 155 | console.log('Received DELETE MCP request'); 156 | res.writeHead(405).end(JSON.stringify({ 157 | jsonrpc: "2.0", 158 | error: { 159 | code: -32000, 160 | message: "Method not allowed." 161 | }, 162 | id: null 163 | })); 164 | }); 165 | 166 | // Start the server 167 | const PORT = 3000; 168 | setupServer().then(() => { 169 | app.listen(PORT, () => { 170 | console.log(`MCP Streamable HTTP Server listening on port ${PORT}`); 171 | }); 172 | }).catch(error => { 173 | console.error('Failed to set up the server:', error); 174 | process.exit(1); 175 | }); 176 | 177 | // Handle server shutdown 178 | process.on('SIGINT', async () => { 179 | console.log('Shutting down server...'); 180 | try { 181 | console.log(`Closing transport`); 182 | await transport.close(); 183 | } catch (error) { 184 | console.error(`Error closing transport:`, error); 185 | } 186 | 187 | await server.close(); 188 | console.log('Server shutdown complete'); 189 | process.exit(0); 190 | }); -------------------------------------------------------------------------------- /mcp-function/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "module": "CommonJS", 5 | "moduleResolution": "node", 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "skipLibCheck": true, 10 | "outDir": "./dist", 11 | "rootDir": "./src", 12 | "declaration": true, 13 | "sourceMap": true 14 | }, 15 | "include": ["src/**/*"], 16 | "exclude": ["node_modules", "dist"] 17 | } 18 | -------------------------------------------------------------------------------- /samconfig.toml: -------------------------------------------------------------------------------- 1 | # More information about the configuration file can be found here: 2 | # https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html 3 | version = 0.1 4 | 5 | [default.global.parameters] 6 | stack_name = "mcp-server-streamable-http" 7 | 8 | [default.build.parameters] 9 | cached = true 10 | parallel = true 11 | 12 | [default.validate.parameters] 13 | lint = true 14 | 15 | [default.deploy.parameters] 16 | capabilities = "CAPABILITY_IAM" 17 | confirm_changeset = false 18 | resolve_s3 = true 19 | stack_name = "mcp-server-streamable-http" 20 | s3_prefix = "mcp-server-streamable-http" 21 | region = "us-east-1" 22 | image_repositories = [] 23 | 24 | [default.package.parameters] 25 | resolve_s3 = true 26 | 27 | [default.sync.parameters] 28 | watch = true 29 | 30 | [default.local_start_api.parameters] 31 | warm_containers = "EAGER" 32 | 33 | [default.local_start_lambda.parameters] 34 | warm_containers = "EAGER" 35 | -------------------------------------------------------------------------------- /template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: > 4 | sam-app 5 | 6 | Sample SAM Template for sam-app with MCP Streamable HTTP Lambda 7 | 8 | # More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst 9 | Globals: 10 | Function: 11 | Timeout: 60 12 | 13 | Resources: 14 | MCPStreamableFunction: 15 | Type: AWS::Serverless::Function 16 | Properties: 17 | CodeUri: mcp-function/ 18 | Handler: run.sh 19 | Runtime: nodejs22.x 20 | MemorySize: 1024 21 | Architectures: 22 | - x86_64 23 | Environment: 24 | Variables: 25 | AWS_LAMBDA_EXEC_WRAPPER: /opt/bootstrap 26 | AWS_LWA_INVOKE_MODE: response_stream 27 | RUST_LOG: info 28 | PORT: 3000 29 | Layers: 30 | - !Sub arn:aws:lambda:${AWS::Region}:753240598075:layer:LambdaAdapterLayerX86:24 31 | FunctionUrlConfig: 32 | AuthType: NONE 33 | InvokeMode: RESPONSE_STREAM 34 | Metadata: 35 | BuildMethod: makefile 36 | 37 | Outputs: 38 | MCPStreamableFunctionUrl: 39 | Description: "Function URL for MCP Streamable HTTP function" 40 | Value: !GetAtt MCPStreamableFunctionUrl.FunctionUrl 41 | MCPStreamableFunction: 42 | Description: "MCP Streamable HTTP Lambda Function ARN" 43 | Value: !GetAtt MCPStreamableFunction.Arn 44 | --------------------------------------------------------------------------------