├── .gitignore ├── README.md ├── main.ts ├── package-lock.json ├── package.json ├── smithery.yaml └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /dist 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `pkgx` MCP 2 | 3 | A [Model Context Protocol] server that can run any Open Source tool via 4 | `pkgx`. 5 | 6 | ## Usage 7 | 8 | 1. Install [`pkgx`] (or not, we download it for you if you don’t) 9 | 2. `git clone https://github.com/pkgxdev/pkgx-mcp` 10 | 3. Consume in an MCP client (see below for configuration examples) 11 | 12 | ### Cursor/Claude Configuation 13 | 14 | - `~/.cursor/mcp.json`: 15 | - `~/Library/Application Support/Claude/claude_desktop_config.json` 16 | 17 | ```json 18 | { 19 | "mcpServers": { 20 | "pkgx": { 21 | "command": "/path/to/pkgx-mcp/main.ts" 22 | } 23 | } 24 | } 25 | ``` 26 | 27 | Or without `pkgx`, but *with* `npx`: 28 | 29 | ```json 30 | { 31 | "mcpServers": { 32 | "pkgx": { 33 | "command": "npx", 34 | "args": ["ts-node", "/path/to/pkgx-mcp/main.ts"] 35 | } 36 | } 37 | } 38 | ``` 39 | 40 | ### MCP Inspector 41 | 42 | ```sh 43 | npx @modelcontextprotocol/inspector ts-node ./main.ts 44 | ``` 45 | 46 | ## Suggested Prompts 47 | 48 | ```text 49 | Use pkgx to run a series of git commands and generate statistics about this 50 | repository. 51 | ``` 52 | 53 | ## Security 54 | 55 | Security? Hah. 56 | 57 | But seriously, this is a dangerous tool. You are letting AI read any file on 58 | your computer†. We have the decency to run `pkgx` in a sandbox so at least a 59 | rogue AI can’t run `rm -rf /`. But we have not restricted reads because that 60 | seemed too limiting. 61 | 62 | We need the MCP protocol to advance to allow the user to be prompted with UI 63 | to approve certain things that the AI cannot by itself do or something like 64 | that. 65 | 66 | In the meantime USE WITH ABSURD AMOUNTS OF CAUTION. 67 | 68 | > † well, on macOS at least we prevent reads to `~/.ssh` and `~/.aws`, PRs 69 | > welcome to exclude more and add Linux sandboxing. 70 | 71 | > [!IMPORTANT] 72 | > 73 | > The AI cannot write to your file system. 74 | > 75 | > On macOS anyway. On Linux we need you to PR that for us. 76 | 77 | [Model Context Protocol]: https://github.com/modelcontextprotocol 78 | [`pkgx`]: https://pkgx.sh 79 | -------------------------------------------------------------------------------- /main.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S pkgx +node@20 npx ts-node 2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; 3 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; 4 | import { CallToolResult } from "@modelcontextprotocol/sdk/types.js"; 5 | import { writeFile, unlink, mkdir } from "fs/promises"; 6 | import { execSync } from "child_process"; 7 | import { platform, tmpdir } from "os"; 8 | import { spawn } from "child_process"; 9 | import { join } from "path"; 10 | import { z } from "zod"; 11 | 12 | const tmp = join(tmpdir(), "pkgx-mcp"); 13 | 14 | const server = new McpServer({ 15 | name: "pkgx-mcp", 16 | version: "0.1.0", 17 | }); 18 | 19 | // Check if running as root 20 | function checkNotRoot(): void { 21 | if (process.getuid && process.getuid() === 0) { 22 | console.error("lol u wot mate? running as root is not allowed."); 23 | process.exit(1); 24 | } 25 | } 26 | 27 | // Execute pkgx command in sandbox 28 | async function runPkgxCommand(program: string, args: string[], cwd?: string): Promise { 29 | let cmd = await get_pkgx(); 30 | args = [program, ...args]; 31 | 32 | let sandboxProfilePath = ""; 33 | if (platform() === "darwin") { 34 | //TODO do the sandbox *after* pkgx so it can have zero writes anywhere 35 | const home = process.env.HOME || process.env.USERPROFILE || ""; 36 | const SANDBOX_PROFILE = ` 37 | (version 1) 38 | (allow default) 39 | (deny file-write*) 40 | (allow file-write* 41 | (subpath "/var") 42 | (subpath "/tmp") 43 | (subpath "/private") 44 | (subpath "/dev/null") 45 | ) 46 | (deny file-read* 47 | (subpath "${home}/.ssh") 48 | (subpath "${home}/.aws") 49 | ) 50 | `; 51 | 52 | sandboxProfilePath = join(tmpdir(), `pkgx_sandbox_${process.pid}_${Math.random().toString(36).substring(2, 15)}.sb`); 53 | await writeFile(sandboxProfilePath, SANDBOX_PROFILE); 54 | args = ["-f", sandboxProfilePath, cmd, ...args]; 55 | cmd = "sandbox-exec"; 56 | } 57 | 58 | try { 59 | // we make our own home so tools like `npx` can cache things since we prohibit writes everywhere else 60 | const HOME = tmp; 61 | const OLD_HOME = process.env.HOME; 62 | 63 | await mkdir(tmp, {recursive: true}); 64 | 65 | const [stdout, stderr] = await new Promise<[string, string]>((resolve, reject) => { 66 | const proc = spawn(cmd, args, { 67 | stdio: ["ignore", "pipe", "pipe"], 68 | env: {...process.env, HOME, OLD_HOME}, 69 | cwd 70 | }); 71 | 72 | let stdout = ""; 73 | proc.stdout.on("data", (data) => { 74 | stdout += data.toString(); 75 | }); 76 | 77 | let stderr = ""; 78 | proc.stderr.on("data", (data) => { 79 | stderr += data.toString(); 80 | }); 81 | 82 | proc.on("close", (code, signal) => { 83 | if (code === 0) { 84 | resolve([stdout, stderr]); 85 | } else { 86 | const title = signal ? `signal(${signal})` : `exit(${code})`; 87 | reject(new Error(JSON.stringify({ code, signal, program, args, cwd, HOME, stderr, stdout, title }))); 88 | } 89 | }); 90 | }); 91 | 92 | return { 93 | content: [{ type: "text", text: JSON.stringify({ stdout, stderr }) }], 94 | }; 95 | } catch (error: any) { 96 | return { 97 | isError: true, 98 | content: [{ 99 | type: "text", 100 | text: error.message, 101 | }] 102 | }; 103 | } finally { 104 | try { 105 | //TODO lets not block u numpty 106 | if (sandboxProfilePath) await unlink(sandboxProfilePath); 107 | } catch (e) { 108 | //noop 109 | } 110 | } 111 | } 112 | 113 | // Parse command line with proper quote handling 114 | function parseCommandLine(cmd: string): [string, string[]] { 115 | const args: string[] = []; 116 | let current = ''; 117 | let inQuote = false; 118 | let quoteChar = ''; 119 | 120 | for (let i = 0; i < cmd.length; i++) { 121 | const char = cmd[i]; 122 | 123 | if (char === '\\' && i + 1 < cmd.length) { 124 | // Handle escaped characters 125 | current += cmd[++i]; 126 | continue; 127 | } 128 | 129 | if ((char === '"' || char === "'") && !inQuote) { 130 | // Start of quoted section 131 | inQuote = true; 132 | quoteChar = char; 133 | continue; 134 | } 135 | 136 | if (char === quoteChar && inQuote) { 137 | // End of quoted section 138 | inQuote = false; 139 | quoteChar = ''; 140 | continue; 141 | } 142 | 143 | if (char === ' ' && !inQuote) { 144 | // Space outside quotes - split argument 145 | if (current) { 146 | args.push(current); 147 | current = ''; 148 | } 149 | continue; 150 | } 151 | 152 | current += char; 153 | } 154 | 155 | // Add the last argument if there is one 156 | if (current) { 157 | args.push(current); 158 | } 159 | 160 | if (args.length === 0) { 161 | return ['', []]; 162 | } 163 | 164 | return [args[0], args.slice(1)]; 165 | } 166 | 167 | server.tool( 168 | "run-command-line", 169 | ` 170 | Run a command line with \`pkgx\`. 171 | The command line can only contain a single program instantiation. 172 | Programs cannot write to the file system. 173 | HOME is set to a temporary directory you can write to. 174 | OLD_HOME is the previous HOME. 175 | Programs do not run in a terminal and thus do not have stdin capabilities. 176 | Shell syntax like pipes \`|\` will not work. 177 | If you need pipes, run the tool multiple times and pipe the output yourself. 178 | `, 179 | { 180 | commandLine: z.string().describe(` 181 | The program to run, pkgx provides almost all open source tools. 182 | The program string can be versioned, eg. \`node@20\`. 183 | Many tools are in npm or pypa—if so set the program to \`npx\` or \`uvx\` and put the tool you want in args!`), 184 | workingDirectory: z.string().default(".").describe(` 185 | Some tools work differently based on the directory they are run in. 186 | Use this parameter accordingly.`) 187 | }, 188 | async ({ commandLine, workingDirectory }) => { 189 | checkNotRoot(); 190 | const [cmd, args] = parseCommandLine(commandLine); 191 | return await runPkgxCommand(cmd, args, workingDirectory == "." ? undefined : workingDirectory); 192 | } 193 | ); 194 | 195 | server.tool( 196 | "run-program-with-array-of-args", 197 | ` 198 | Run a single program with \`pkgx\`. 199 | Programs cannot write to the file system. 200 | HOME is set to a temporary directory you can write to. 201 | OLD_HOME is the previous HOME. 202 | Programs do not run in a terminal and thus do not have stdin capabilities. 203 | Shell syntax like pipes \`|\` will not work. 204 | If you need pipes, run the tool multiple times and pipe the output yourself. 205 | The \`args\` parameter must be an array of strings. 206 | `, 207 | { 208 | program: z.string().describe(` 209 | The program to run, pkgx provides almost all open source tools. 210 | The program string can be versioned, eg. \`node@20\`. 211 | Many tools are in npm or pypa—if so set the program to \`npx\` or \`uvx\` and put the tool you want in args!`), 212 | args: z.array(z.string()).default([]).describe(` 213 | Arguments to pass to the program. 214 | The program is not run inside a shell, so do not use shell syntax like pipes. 215 | Shell quoting rules should also be ignored, any quotes will be passed directly to the program. 216 | `), 217 | workingDirectory: z.string().default(".").describe(` 218 | Some tools work differently based on the directory they are run in. 219 | Use this parameter accordingly.`) 220 | }, 221 | async ({ program, args, workingDirectory }) => { 222 | checkNotRoot(); 223 | return await runPkgxCommand(program, args, workingDirectory == "." ? undefined : workingDirectory); 224 | } 225 | ); 226 | 227 | server.resource( 228 | "list-runnable-programs", 229 | "pkgx://programs/list", 230 | async (uri) => { 231 | const result = execSync("pkgx -Q", { stdio: ["inherit", "pipe", "inherit"] }); 232 | return { 233 | contents: [{ 234 | uri: uri.href, 235 | text: result.toString(), 236 | }] 237 | } 238 | } 239 | ) 240 | 241 | server.resource( 242 | "list-mash-scripts", 243 | "pkgx://mash/list", 244 | async (uri) => { 245 | const rsp = await fetch("https://pkgxdev.github.io/mash/index.json"); 246 | const text = await rsp.text(); 247 | return { 248 | contents: [{ 249 | uri: uri.href, 250 | text, 251 | }] 252 | } 253 | } 254 | ) 255 | 256 | const transport = new StdioServerTransport(); 257 | 258 | server.connect(transport).catch((err) => { 259 | console.error(`Server failed: ${err}`); 260 | process.exit(1); 261 | }); 262 | 263 | async function get_pkgx() { 264 | try { 265 | execSync("pkgx --version") 266 | throw new Error(); 267 | return "pkgx"; 268 | } catch { 269 | const platform = (() => { 270 | switch (`${process.platform}/${process.arch}`) { 271 | case "linux/x64": 272 | return "Linux/x86-64" 273 | case "linux/arm64": 274 | return "Linux/arm64" 275 | case "darwin/arm64": 276 | return "Darwin/arm64" 277 | case "darwin/x64": 278 | return "Darwin/x86-64" 279 | default: 280 | throw new Error(`Unsupported platform: ${process.platform}/${process.arch}`); 281 | } 282 | })() 283 | 284 | await mkdir(tmp, {recursive: true}); 285 | 286 | const url = `https://pkgx.sh/${platform}`; 287 | const filePath = join(tmp, "pkgx"); 288 | const response = await fetch(url); 289 | 290 | if (!response.ok) { 291 | throw new Error(`Failed to download pkgx: ${response.statusText}`); 292 | } 293 | 294 | const fileBuffer = await response.arrayBuffer(); 295 | await writeFile(filePath, Buffer.from(fileBuffer), { mode: 0o755 }); 296 | 297 | return filePath; 298 | } 299 | } 300 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pkgmcp", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "dependencies": { 8 | "@modelcontextprotocol/sdk": "^1.10.2", 9 | "@types/node": "^22.15.2", 10 | "typescript": "^5.8.3" 11 | }, 12 | "engines": { 13 | "node": "^20" 14 | } 15 | }, 16 | "node_modules/@modelcontextprotocol/sdk": { 17 | "version": "1.10.2", 18 | "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.10.2.tgz", 19 | "integrity": "sha512-rb6AMp2DR4SN+kc6L1ta2NCpApyA9WYNx3CrTSZvGxq9wH71bRur+zRqPfg0vQ9mjywR7qZdX2RGHOPq3ss+tA==", 20 | "license": "MIT", 21 | "dependencies": { 22 | "content-type": "^1.0.5", 23 | "cors": "^2.8.5", 24 | "cross-spawn": "^7.0.3", 25 | "eventsource": "^3.0.2", 26 | "express": "^5.0.1", 27 | "express-rate-limit": "^7.5.0", 28 | "pkce-challenge": "^5.0.0", 29 | "raw-body": "^3.0.0", 30 | "zod": "^3.23.8", 31 | "zod-to-json-schema": "^3.24.1" 32 | }, 33 | "engines": { 34 | "node": ">=18" 35 | } 36 | }, 37 | "node_modules/@types/node": { 38 | "version": "22.15.2", 39 | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.2.tgz", 40 | "integrity": "sha512-uKXqKN9beGoMdBfcaTY1ecwz6ctxuJAcUlwE55938g0ZJ8lRxwAZqRz2AJ4pzpt5dHdTPMB863UZ0ESiFUcP7A==", 41 | "license": "MIT", 42 | "dependencies": { 43 | "undici-types": "~6.21.0" 44 | } 45 | }, 46 | "node_modules/accepts": { 47 | "version": "2.0.0", 48 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", 49 | "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", 50 | "license": "MIT", 51 | "dependencies": { 52 | "mime-types": "^3.0.0", 53 | "negotiator": "^1.0.0" 54 | }, 55 | "engines": { 56 | "node": ">= 0.6" 57 | } 58 | }, 59 | "node_modules/body-parser": { 60 | "version": "2.2.0", 61 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", 62 | "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", 63 | "license": "MIT", 64 | "dependencies": { 65 | "bytes": "^3.1.2", 66 | "content-type": "^1.0.5", 67 | "debug": "^4.4.0", 68 | "http-errors": "^2.0.0", 69 | "iconv-lite": "^0.6.3", 70 | "on-finished": "^2.4.1", 71 | "qs": "^6.14.0", 72 | "raw-body": "^3.0.0", 73 | "type-is": "^2.0.0" 74 | }, 75 | "engines": { 76 | "node": ">=18" 77 | } 78 | }, 79 | "node_modules/bytes": { 80 | "version": "3.1.2", 81 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 82 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 83 | "license": "MIT", 84 | "engines": { 85 | "node": ">= 0.8" 86 | } 87 | }, 88 | "node_modules/call-bind-apply-helpers": { 89 | "version": "1.0.2", 90 | "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", 91 | "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", 92 | "license": "MIT", 93 | "dependencies": { 94 | "es-errors": "^1.3.0", 95 | "function-bind": "^1.1.2" 96 | }, 97 | "engines": { 98 | "node": ">= 0.4" 99 | } 100 | }, 101 | "node_modules/call-bound": { 102 | "version": "1.0.4", 103 | "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", 104 | "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", 105 | "license": "MIT", 106 | "dependencies": { 107 | "call-bind-apply-helpers": "^1.0.2", 108 | "get-intrinsic": "^1.3.0" 109 | }, 110 | "engines": { 111 | "node": ">= 0.4" 112 | }, 113 | "funding": { 114 | "url": "https://github.com/sponsors/ljharb" 115 | } 116 | }, 117 | "node_modules/content-disposition": { 118 | "version": "1.0.0", 119 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", 120 | "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", 121 | "license": "MIT", 122 | "dependencies": { 123 | "safe-buffer": "5.2.1" 124 | }, 125 | "engines": { 126 | "node": ">= 0.6" 127 | } 128 | }, 129 | "node_modules/content-type": { 130 | "version": "1.0.5", 131 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 132 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 133 | "license": "MIT", 134 | "engines": { 135 | "node": ">= 0.6" 136 | } 137 | }, 138 | "node_modules/cookie": { 139 | "version": "0.7.2", 140 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", 141 | "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", 142 | "license": "MIT", 143 | "engines": { 144 | "node": ">= 0.6" 145 | } 146 | }, 147 | "node_modules/cookie-signature": { 148 | "version": "1.2.2", 149 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", 150 | "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", 151 | "license": "MIT", 152 | "engines": { 153 | "node": ">=6.6.0" 154 | } 155 | }, 156 | "node_modules/cors": { 157 | "version": "2.8.5", 158 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 159 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 160 | "license": "MIT", 161 | "dependencies": { 162 | "object-assign": "^4", 163 | "vary": "^1" 164 | }, 165 | "engines": { 166 | "node": ">= 0.10" 167 | } 168 | }, 169 | "node_modules/cross-spawn": { 170 | "version": "7.0.6", 171 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", 172 | "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", 173 | "license": "MIT", 174 | "dependencies": { 175 | "path-key": "^3.1.0", 176 | "shebang-command": "^2.0.0", 177 | "which": "^2.0.1" 178 | }, 179 | "engines": { 180 | "node": ">= 8" 181 | } 182 | }, 183 | "node_modules/debug": { 184 | "version": "4.4.0", 185 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 186 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 187 | "license": "MIT", 188 | "dependencies": { 189 | "ms": "^2.1.3" 190 | }, 191 | "engines": { 192 | "node": ">=6.0" 193 | }, 194 | "peerDependenciesMeta": { 195 | "supports-color": { 196 | "optional": true 197 | } 198 | } 199 | }, 200 | "node_modules/depd": { 201 | "version": "2.0.0", 202 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 203 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 204 | "license": "MIT", 205 | "engines": { 206 | "node": ">= 0.8" 207 | } 208 | }, 209 | "node_modules/dunder-proto": { 210 | "version": "1.0.1", 211 | "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 212 | "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 213 | "license": "MIT", 214 | "dependencies": { 215 | "call-bind-apply-helpers": "^1.0.1", 216 | "es-errors": "^1.3.0", 217 | "gopd": "^1.2.0" 218 | }, 219 | "engines": { 220 | "node": ">= 0.4" 221 | } 222 | }, 223 | "node_modules/ee-first": { 224 | "version": "1.1.1", 225 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 226 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", 227 | "license": "MIT" 228 | }, 229 | "node_modules/encodeurl": { 230 | "version": "2.0.0", 231 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 232 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 233 | "license": "MIT", 234 | "engines": { 235 | "node": ">= 0.8" 236 | } 237 | }, 238 | "node_modules/es-define-property": { 239 | "version": "1.0.1", 240 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 241 | "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 242 | "license": "MIT", 243 | "engines": { 244 | "node": ">= 0.4" 245 | } 246 | }, 247 | "node_modules/es-errors": { 248 | "version": "1.3.0", 249 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 250 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 251 | "license": "MIT", 252 | "engines": { 253 | "node": ">= 0.4" 254 | } 255 | }, 256 | "node_modules/es-object-atoms": { 257 | "version": "1.1.1", 258 | "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", 259 | "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", 260 | "license": "MIT", 261 | "dependencies": { 262 | "es-errors": "^1.3.0" 263 | }, 264 | "engines": { 265 | "node": ">= 0.4" 266 | } 267 | }, 268 | "node_modules/escape-html": { 269 | "version": "1.0.3", 270 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 271 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", 272 | "license": "MIT" 273 | }, 274 | "node_modules/etag": { 275 | "version": "1.8.1", 276 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 277 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 278 | "license": "MIT", 279 | "engines": { 280 | "node": ">= 0.6" 281 | } 282 | }, 283 | "node_modules/eventsource": { 284 | "version": "3.0.6", 285 | "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.6.tgz", 286 | "integrity": "sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA==", 287 | "license": "MIT", 288 | "dependencies": { 289 | "eventsource-parser": "^3.0.1" 290 | }, 291 | "engines": { 292 | "node": ">=18.0.0" 293 | } 294 | }, 295 | "node_modules/eventsource-parser": { 296 | "version": "3.0.1", 297 | "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz", 298 | "integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==", 299 | "license": "MIT", 300 | "engines": { 301 | "node": ">=18.0.0" 302 | } 303 | }, 304 | "node_modules/express": { 305 | "version": "5.1.0", 306 | "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", 307 | "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", 308 | "license": "MIT", 309 | "dependencies": { 310 | "accepts": "^2.0.0", 311 | "body-parser": "^2.2.0", 312 | "content-disposition": "^1.0.0", 313 | "content-type": "^1.0.5", 314 | "cookie": "^0.7.1", 315 | "cookie-signature": "^1.2.1", 316 | "debug": "^4.4.0", 317 | "encodeurl": "^2.0.0", 318 | "escape-html": "^1.0.3", 319 | "etag": "^1.8.1", 320 | "finalhandler": "^2.1.0", 321 | "fresh": "^2.0.0", 322 | "http-errors": "^2.0.0", 323 | "merge-descriptors": "^2.0.0", 324 | "mime-types": "^3.0.0", 325 | "on-finished": "^2.4.1", 326 | "once": "^1.4.0", 327 | "parseurl": "^1.3.3", 328 | "proxy-addr": "^2.0.7", 329 | "qs": "^6.14.0", 330 | "range-parser": "^1.2.1", 331 | "router": "^2.2.0", 332 | "send": "^1.1.0", 333 | "serve-static": "^2.2.0", 334 | "statuses": "^2.0.1", 335 | "type-is": "^2.0.1", 336 | "vary": "^1.1.2" 337 | }, 338 | "engines": { 339 | "node": ">= 18" 340 | }, 341 | "funding": { 342 | "type": "opencollective", 343 | "url": "https://opencollective.com/express" 344 | } 345 | }, 346 | "node_modules/express-rate-limit": { 347 | "version": "7.5.0", 348 | "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", 349 | "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", 350 | "license": "MIT", 351 | "engines": { 352 | "node": ">= 16" 353 | }, 354 | "funding": { 355 | "url": "https://github.com/sponsors/express-rate-limit" 356 | }, 357 | "peerDependencies": { 358 | "express": "^4.11 || 5 || ^5.0.0-beta.1" 359 | } 360 | }, 361 | "node_modules/finalhandler": { 362 | "version": "2.1.0", 363 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", 364 | "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", 365 | "license": "MIT", 366 | "dependencies": { 367 | "debug": "^4.4.0", 368 | "encodeurl": "^2.0.0", 369 | "escape-html": "^1.0.3", 370 | "on-finished": "^2.4.1", 371 | "parseurl": "^1.3.3", 372 | "statuses": "^2.0.1" 373 | }, 374 | "engines": { 375 | "node": ">= 0.8" 376 | } 377 | }, 378 | "node_modules/forwarded": { 379 | "version": "0.2.0", 380 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 381 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 382 | "license": "MIT", 383 | "engines": { 384 | "node": ">= 0.6" 385 | } 386 | }, 387 | "node_modules/fresh": { 388 | "version": "2.0.0", 389 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", 390 | "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", 391 | "license": "MIT", 392 | "engines": { 393 | "node": ">= 0.8" 394 | } 395 | }, 396 | "node_modules/function-bind": { 397 | "version": "1.1.2", 398 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 399 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 400 | "license": "MIT", 401 | "funding": { 402 | "url": "https://github.com/sponsors/ljharb" 403 | } 404 | }, 405 | "node_modules/get-intrinsic": { 406 | "version": "1.3.0", 407 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", 408 | "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", 409 | "license": "MIT", 410 | "dependencies": { 411 | "call-bind-apply-helpers": "^1.0.2", 412 | "es-define-property": "^1.0.1", 413 | "es-errors": "^1.3.0", 414 | "es-object-atoms": "^1.1.1", 415 | "function-bind": "^1.1.2", 416 | "get-proto": "^1.0.1", 417 | "gopd": "^1.2.0", 418 | "has-symbols": "^1.1.0", 419 | "hasown": "^2.0.2", 420 | "math-intrinsics": "^1.1.0" 421 | }, 422 | "engines": { 423 | "node": ">= 0.4" 424 | }, 425 | "funding": { 426 | "url": "https://github.com/sponsors/ljharb" 427 | } 428 | }, 429 | "node_modules/get-proto": { 430 | "version": "1.0.1", 431 | "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", 432 | "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", 433 | "license": "MIT", 434 | "dependencies": { 435 | "dunder-proto": "^1.0.1", 436 | "es-object-atoms": "^1.0.0" 437 | }, 438 | "engines": { 439 | "node": ">= 0.4" 440 | } 441 | }, 442 | "node_modules/gopd": { 443 | "version": "1.2.0", 444 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 445 | "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 446 | "license": "MIT", 447 | "engines": { 448 | "node": ">= 0.4" 449 | }, 450 | "funding": { 451 | "url": "https://github.com/sponsors/ljharb" 452 | } 453 | }, 454 | "node_modules/has-symbols": { 455 | "version": "1.1.0", 456 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 457 | "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 458 | "license": "MIT", 459 | "engines": { 460 | "node": ">= 0.4" 461 | }, 462 | "funding": { 463 | "url": "https://github.com/sponsors/ljharb" 464 | } 465 | }, 466 | "node_modules/hasown": { 467 | "version": "2.0.2", 468 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 469 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 470 | "license": "MIT", 471 | "dependencies": { 472 | "function-bind": "^1.1.2" 473 | }, 474 | "engines": { 475 | "node": ">= 0.4" 476 | } 477 | }, 478 | "node_modules/http-errors": { 479 | "version": "2.0.0", 480 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 481 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 482 | "license": "MIT", 483 | "dependencies": { 484 | "depd": "2.0.0", 485 | "inherits": "2.0.4", 486 | "setprototypeof": "1.2.0", 487 | "statuses": "2.0.1", 488 | "toidentifier": "1.0.1" 489 | }, 490 | "engines": { 491 | "node": ">= 0.8" 492 | } 493 | }, 494 | "node_modules/iconv-lite": { 495 | "version": "0.6.3", 496 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 497 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 498 | "license": "MIT", 499 | "dependencies": { 500 | "safer-buffer": ">= 2.1.2 < 3.0.0" 501 | }, 502 | "engines": { 503 | "node": ">=0.10.0" 504 | } 505 | }, 506 | "node_modules/inherits": { 507 | "version": "2.0.4", 508 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 509 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 510 | "license": "ISC" 511 | }, 512 | "node_modules/ipaddr.js": { 513 | "version": "1.9.1", 514 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 515 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 516 | "license": "MIT", 517 | "engines": { 518 | "node": ">= 0.10" 519 | } 520 | }, 521 | "node_modules/is-promise": { 522 | "version": "4.0.0", 523 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", 524 | "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", 525 | "license": "MIT" 526 | }, 527 | "node_modules/isexe": { 528 | "version": "2.0.0", 529 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 530 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 531 | "license": "ISC" 532 | }, 533 | "node_modules/math-intrinsics": { 534 | "version": "1.1.0", 535 | "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 536 | "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 537 | "license": "MIT", 538 | "engines": { 539 | "node": ">= 0.4" 540 | } 541 | }, 542 | "node_modules/media-typer": { 543 | "version": "1.1.0", 544 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", 545 | "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", 546 | "license": "MIT", 547 | "engines": { 548 | "node": ">= 0.8" 549 | } 550 | }, 551 | "node_modules/merge-descriptors": { 552 | "version": "2.0.0", 553 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", 554 | "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", 555 | "license": "MIT", 556 | "engines": { 557 | "node": ">=18" 558 | }, 559 | "funding": { 560 | "url": "https://github.com/sponsors/sindresorhus" 561 | } 562 | }, 563 | "node_modules/mime-db": { 564 | "version": "1.54.0", 565 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", 566 | "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", 567 | "license": "MIT", 568 | "engines": { 569 | "node": ">= 0.6" 570 | } 571 | }, 572 | "node_modules/mime-types": { 573 | "version": "3.0.1", 574 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", 575 | "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", 576 | "license": "MIT", 577 | "dependencies": { 578 | "mime-db": "^1.54.0" 579 | }, 580 | "engines": { 581 | "node": ">= 0.6" 582 | } 583 | }, 584 | "node_modules/ms": { 585 | "version": "2.1.3", 586 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 587 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 588 | "license": "MIT" 589 | }, 590 | "node_modules/negotiator": { 591 | "version": "1.0.0", 592 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", 593 | "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", 594 | "license": "MIT", 595 | "engines": { 596 | "node": ">= 0.6" 597 | } 598 | }, 599 | "node_modules/object-assign": { 600 | "version": "4.1.1", 601 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 602 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 603 | "license": "MIT", 604 | "engines": { 605 | "node": ">=0.10.0" 606 | } 607 | }, 608 | "node_modules/object-inspect": { 609 | "version": "1.13.4", 610 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", 611 | "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", 612 | "license": "MIT", 613 | "engines": { 614 | "node": ">= 0.4" 615 | }, 616 | "funding": { 617 | "url": "https://github.com/sponsors/ljharb" 618 | } 619 | }, 620 | "node_modules/on-finished": { 621 | "version": "2.4.1", 622 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 623 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 624 | "license": "MIT", 625 | "dependencies": { 626 | "ee-first": "1.1.1" 627 | }, 628 | "engines": { 629 | "node": ">= 0.8" 630 | } 631 | }, 632 | "node_modules/once": { 633 | "version": "1.4.0", 634 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 635 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 636 | "license": "ISC", 637 | "dependencies": { 638 | "wrappy": "1" 639 | } 640 | }, 641 | "node_modules/parseurl": { 642 | "version": "1.3.3", 643 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 644 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 645 | "license": "MIT", 646 | "engines": { 647 | "node": ">= 0.8" 648 | } 649 | }, 650 | "node_modules/path-key": { 651 | "version": "3.1.1", 652 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 653 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 654 | "license": "MIT", 655 | "engines": { 656 | "node": ">=8" 657 | } 658 | }, 659 | "node_modules/path-to-regexp": { 660 | "version": "8.2.0", 661 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", 662 | "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", 663 | "license": "MIT", 664 | "engines": { 665 | "node": ">=16" 666 | } 667 | }, 668 | "node_modules/pkce-challenge": { 669 | "version": "5.0.0", 670 | "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", 671 | "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", 672 | "license": "MIT", 673 | "engines": { 674 | "node": ">=16.20.0" 675 | } 676 | }, 677 | "node_modules/proxy-addr": { 678 | "version": "2.0.7", 679 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 680 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 681 | "license": "MIT", 682 | "dependencies": { 683 | "forwarded": "0.2.0", 684 | "ipaddr.js": "1.9.1" 685 | }, 686 | "engines": { 687 | "node": ">= 0.10" 688 | } 689 | }, 690 | "node_modules/qs": { 691 | "version": "6.14.0", 692 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", 693 | "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", 694 | "license": "BSD-3-Clause", 695 | "dependencies": { 696 | "side-channel": "^1.1.0" 697 | }, 698 | "engines": { 699 | "node": ">=0.6" 700 | }, 701 | "funding": { 702 | "url": "https://github.com/sponsors/ljharb" 703 | } 704 | }, 705 | "node_modules/range-parser": { 706 | "version": "1.2.1", 707 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 708 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 709 | "license": "MIT", 710 | "engines": { 711 | "node": ">= 0.6" 712 | } 713 | }, 714 | "node_modules/raw-body": { 715 | "version": "3.0.0", 716 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", 717 | "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", 718 | "license": "MIT", 719 | "dependencies": { 720 | "bytes": "3.1.2", 721 | "http-errors": "2.0.0", 722 | "iconv-lite": "0.6.3", 723 | "unpipe": "1.0.0" 724 | }, 725 | "engines": { 726 | "node": ">= 0.8" 727 | } 728 | }, 729 | "node_modules/router": { 730 | "version": "2.2.0", 731 | "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", 732 | "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", 733 | "license": "MIT", 734 | "dependencies": { 735 | "debug": "^4.4.0", 736 | "depd": "^2.0.0", 737 | "is-promise": "^4.0.0", 738 | "parseurl": "^1.3.3", 739 | "path-to-regexp": "^8.0.0" 740 | }, 741 | "engines": { 742 | "node": ">= 18" 743 | } 744 | }, 745 | "node_modules/safe-buffer": { 746 | "version": "5.2.1", 747 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 748 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 749 | "funding": [ 750 | { 751 | "type": "github", 752 | "url": "https://github.com/sponsors/feross" 753 | }, 754 | { 755 | "type": "patreon", 756 | "url": "https://www.patreon.com/feross" 757 | }, 758 | { 759 | "type": "consulting", 760 | "url": "https://feross.org/support" 761 | } 762 | ], 763 | "license": "MIT" 764 | }, 765 | "node_modules/safer-buffer": { 766 | "version": "2.1.2", 767 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 768 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 769 | "license": "MIT" 770 | }, 771 | "node_modules/send": { 772 | "version": "1.2.0", 773 | "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", 774 | "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", 775 | "license": "MIT", 776 | "dependencies": { 777 | "debug": "^4.3.5", 778 | "encodeurl": "^2.0.0", 779 | "escape-html": "^1.0.3", 780 | "etag": "^1.8.1", 781 | "fresh": "^2.0.0", 782 | "http-errors": "^2.0.0", 783 | "mime-types": "^3.0.1", 784 | "ms": "^2.1.3", 785 | "on-finished": "^2.4.1", 786 | "range-parser": "^1.2.1", 787 | "statuses": "^2.0.1" 788 | }, 789 | "engines": { 790 | "node": ">= 18" 791 | } 792 | }, 793 | "node_modules/serve-static": { 794 | "version": "2.2.0", 795 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", 796 | "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", 797 | "license": "MIT", 798 | "dependencies": { 799 | "encodeurl": "^2.0.0", 800 | "escape-html": "^1.0.3", 801 | "parseurl": "^1.3.3", 802 | "send": "^1.2.0" 803 | }, 804 | "engines": { 805 | "node": ">= 18" 806 | } 807 | }, 808 | "node_modules/setprototypeof": { 809 | "version": "1.2.0", 810 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 811 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", 812 | "license": "ISC" 813 | }, 814 | "node_modules/shebang-command": { 815 | "version": "2.0.0", 816 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 817 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 818 | "license": "MIT", 819 | "dependencies": { 820 | "shebang-regex": "^3.0.0" 821 | }, 822 | "engines": { 823 | "node": ">=8" 824 | } 825 | }, 826 | "node_modules/shebang-regex": { 827 | "version": "3.0.0", 828 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 829 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 830 | "license": "MIT", 831 | "engines": { 832 | "node": ">=8" 833 | } 834 | }, 835 | "node_modules/side-channel": { 836 | "version": "1.1.0", 837 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", 838 | "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", 839 | "license": "MIT", 840 | "dependencies": { 841 | "es-errors": "^1.3.0", 842 | "object-inspect": "^1.13.3", 843 | "side-channel-list": "^1.0.0", 844 | "side-channel-map": "^1.0.1", 845 | "side-channel-weakmap": "^1.0.2" 846 | }, 847 | "engines": { 848 | "node": ">= 0.4" 849 | }, 850 | "funding": { 851 | "url": "https://github.com/sponsors/ljharb" 852 | } 853 | }, 854 | "node_modules/side-channel-list": { 855 | "version": "1.0.0", 856 | "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", 857 | "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", 858 | "license": "MIT", 859 | "dependencies": { 860 | "es-errors": "^1.3.0", 861 | "object-inspect": "^1.13.3" 862 | }, 863 | "engines": { 864 | "node": ">= 0.4" 865 | }, 866 | "funding": { 867 | "url": "https://github.com/sponsors/ljharb" 868 | } 869 | }, 870 | "node_modules/side-channel-map": { 871 | "version": "1.0.1", 872 | "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", 873 | "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", 874 | "license": "MIT", 875 | "dependencies": { 876 | "call-bound": "^1.0.2", 877 | "es-errors": "^1.3.0", 878 | "get-intrinsic": "^1.2.5", 879 | "object-inspect": "^1.13.3" 880 | }, 881 | "engines": { 882 | "node": ">= 0.4" 883 | }, 884 | "funding": { 885 | "url": "https://github.com/sponsors/ljharb" 886 | } 887 | }, 888 | "node_modules/side-channel-weakmap": { 889 | "version": "1.0.2", 890 | "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", 891 | "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", 892 | "license": "MIT", 893 | "dependencies": { 894 | "call-bound": "^1.0.2", 895 | "es-errors": "^1.3.0", 896 | "get-intrinsic": "^1.2.5", 897 | "object-inspect": "^1.13.3", 898 | "side-channel-map": "^1.0.1" 899 | }, 900 | "engines": { 901 | "node": ">= 0.4" 902 | }, 903 | "funding": { 904 | "url": "https://github.com/sponsors/ljharb" 905 | } 906 | }, 907 | "node_modules/statuses": { 908 | "version": "2.0.1", 909 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 910 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 911 | "license": "MIT", 912 | "engines": { 913 | "node": ">= 0.8" 914 | } 915 | }, 916 | "node_modules/toidentifier": { 917 | "version": "1.0.1", 918 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 919 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 920 | "license": "MIT", 921 | "engines": { 922 | "node": ">=0.6" 923 | } 924 | }, 925 | "node_modules/type-is": { 926 | "version": "2.0.1", 927 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", 928 | "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", 929 | "license": "MIT", 930 | "dependencies": { 931 | "content-type": "^1.0.5", 932 | "media-typer": "^1.1.0", 933 | "mime-types": "^3.0.0" 934 | }, 935 | "engines": { 936 | "node": ">= 0.6" 937 | } 938 | }, 939 | "node_modules/typescript": { 940 | "version": "5.8.3", 941 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", 942 | "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", 943 | "license": "Apache-2.0", 944 | "bin": { 945 | "tsc": "bin/tsc", 946 | "tsserver": "bin/tsserver" 947 | }, 948 | "engines": { 949 | "node": ">=14.17" 950 | } 951 | }, 952 | "node_modules/undici-types": { 953 | "version": "6.21.0", 954 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", 955 | "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", 956 | "license": "MIT" 957 | }, 958 | "node_modules/unpipe": { 959 | "version": "1.0.0", 960 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 961 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 962 | "license": "MIT", 963 | "engines": { 964 | "node": ">= 0.8" 965 | } 966 | }, 967 | "node_modules/vary": { 968 | "version": "1.1.2", 969 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 970 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 971 | "license": "MIT", 972 | "engines": { 973 | "node": ">= 0.8" 974 | } 975 | }, 976 | "node_modules/which": { 977 | "version": "2.0.2", 978 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 979 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 980 | "license": "ISC", 981 | "dependencies": { 982 | "isexe": "^2.0.0" 983 | }, 984 | "bin": { 985 | "node-which": "bin/node-which" 986 | }, 987 | "engines": { 988 | "node": ">= 8" 989 | } 990 | }, 991 | "node_modules/wrappy": { 992 | "version": "1.0.2", 993 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 994 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 995 | "license": "ISC" 996 | }, 997 | "node_modules/zod": { 998 | "version": "3.24.3", 999 | "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.3.tgz", 1000 | "integrity": "sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==", 1001 | "license": "MIT", 1002 | "funding": { 1003 | "url": "https://github.com/sponsors/colinhacks" 1004 | } 1005 | }, 1006 | "node_modules/zod-to-json-schema": { 1007 | "version": "3.24.5", 1008 | "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.5.tgz", 1009 | "integrity": "sha512-/AuWwMP+YqiPbsJx5D6TfgRTc4kTLjsh5SOcd4bLsfUg2RcEXrFMJl1DGgdHy2aCfsIA/cr/1JM0xcB2GZji8g==", 1010 | "license": "ISC", 1011 | "peerDependencies": { 1012 | "zod": "^3.24.1" 1013 | } 1014 | } 1015 | } 1016 | } 1017 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@modelcontextprotocol/sdk": "^1.10.2", 4 | "@types/node": "^22.15.2", 5 | "typescript": "^5.8.3" 6 | }, 7 | "engines": { 8 | "node": "^20" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /smithery.yaml: -------------------------------------------------------------------------------- 1 | startCommand: 2 | type: stdio 3 | configSchema: {} 4 | 5 | commandFunction: |- 6 | (config) => ({ 7 | "command": "npx", 8 | "args": ["ts-node", "main.ts"] 9 | }) 10 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "commonjs", 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "moduleResolution": "node", 8 | "outDir": "./dist", 9 | "types": ["node"] 10 | }, 11 | "include": ["*.ts"] 12 | } --------------------------------------------------------------------------------