webui: Add MCP CORS Proxy detection logic & UI (#20167)
* refactor: MCP store cleanup * feat: Add MCP proxy availability detection * fix: Sidebar icon * chore: update webui build output * chore: Formatting * chore: update webui build output * chore: Update package lock * chore: update webui build output * chore: update webui build output * chore: update webui build output
This commit is contained in:
Binary file not shown.
Generated
+3
-30
@@ -939,7 +939,6 @@
|
|||||||
"integrity": "sha512-oJrXtQiAXLvT9clCf1K4kxp3eKsQhIaZqxEyowkBcsvZDdZkbWrVmnGknxs5flTD0VGsxrxKgBCZty1EzoiMzA==",
|
"integrity": "sha512-oJrXtQiAXLvT9clCf1K4kxp3eKsQhIaZqxEyowkBcsvZDdZkbWrVmnGknxs5flTD0VGsxrxKgBCZty1EzoiMzA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@swc/helpers": "^0.5.0"
|
"@swc/helpers": "^0.5.0"
|
||||||
}
|
}
|
||||||
@@ -2161,7 +2160,6 @@
|
|||||||
"integrity": "sha512-W9R51zUCd2iHOQBg/D93+bdpYv6kbtFx+kft5X8lPKQl6yEu0aKs9i5N5GyCASOhIApgx/tkqZIJ7vgM4cqrHA==",
|
"integrity": "sha512-W9R51zUCd2iHOQBg/D93+bdpYv6kbtFx+kft5X8lPKQl6yEu0aKs9i5N5GyCASOhIApgx/tkqZIJ7vgM4cqrHA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ts-dedent": "^2.0.0",
|
"ts-dedent": "^2.0.0",
|
||||||
"type-fest": "~2.19"
|
"type-fest": "~2.19"
|
||||||
@@ -2245,7 +2243,6 @@
|
|||||||
"integrity": "sha512-875hTUkEbz+MyJIxWbQjfMaekqdmEKUUfR7JyKcpfMRZqcGyrO9Gd+iS1D/Dx8LpE5FEtutWGOtlAh4ReSAiOA==",
|
"integrity": "sha512-875hTUkEbz+MyJIxWbQjfMaekqdmEKUUfR7JyKcpfMRZqcGyrO9Gd+iS1D/Dx8LpE5FEtutWGOtlAh4ReSAiOA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@standard-schema/spec": "^1.0.0",
|
"@standard-schema/spec": "^1.0.0",
|
||||||
"@sveltejs/acorn-typescript": "^1.0.5",
|
"@sveltejs/acorn-typescript": "^1.0.5",
|
||||||
@@ -2289,7 +2286,6 @@
|
|||||||
"integrity": "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==",
|
"integrity": "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sveltejs/vite-plugin-svelte-inspector": "^5.0.0",
|
"@sveltejs/vite-plugin-svelte-inspector": "^5.0.0",
|
||||||
"debug": "^4.4.1",
|
"debug": "^4.4.1",
|
||||||
@@ -2705,7 +2701,6 @@
|
|||||||
"integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==",
|
"integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": "^7.10.4",
|
"@babel/code-frame": "^7.10.4",
|
||||||
"@babel/runtime": "^7.12.5",
|
"@babel/runtime": "^7.12.5",
|
||||||
@@ -2873,7 +2868,6 @@
|
|||||||
"integrity": "sha512-+0/4J266CBGPUq/ELg7QUHhN25WYjE0wYTPSQJn1xeu8DOlIOPxXxrNGiLmfAWl7HMMgWFWXpt9IDjMWrF5Iow==",
|
"integrity": "sha512-+0/4J266CBGPUq/ELg7QUHhN25WYjE0wYTPSQJn1xeu8DOlIOPxXxrNGiLmfAWl7HMMgWFWXpt9IDjMWrF5Iow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"undici-types": "~7.16.0"
|
"undici-types": "~7.16.0"
|
||||||
}
|
}
|
||||||
@@ -2940,7 +2934,6 @@
|
|||||||
"integrity": "sha512-IgSWvLobTDOjnaxAfDTIHaECbkNlAlKv2j5SjpB2v7QHKv1FIfjwMy8FsDbVfDX/KjmCmYICcw7uGaXLhtsLNg==",
|
"integrity": "sha512-IgSWvLobTDOjnaxAfDTIHaECbkNlAlKv2j5SjpB2v7QHKv1FIfjwMy8FsDbVfDX/KjmCmYICcw7uGaXLhtsLNg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "8.56.0",
|
"@typescript-eslint/scope-manager": "8.56.0",
|
||||||
"@typescript-eslint/types": "8.56.0",
|
"@typescript-eslint/types": "8.56.0",
|
||||||
@@ -3177,7 +3170,6 @@
|
|||||||
"integrity": "sha512-tJxiPrWmzH8a+w9nLKlQMzAKX/7VjFs50MWgcAj7p9XQ7AQ9/35fByFYptgPELyLw+0aixTnC4pUWV+APcZ/kw==",
|
"integrity": "sha512-tJxiPrWmzH8a+w9nLKlQMzAKX/7VjFs50MWgcAj7p9XQ7AQ9/35fByFYptgPELyLw+0aixTnC4pUWV+APcZ/kw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@testing-library/dom": "^10.4.0",
|
"@testing-library/dom": "^10.4.0",
|
||||||
"@testing-library/user-event": "^14.6.1",
|
"@testing-library/user-event": "^14.6.1",
|
||||||
@@ -3305,7 +3297,6 @@
|
|||||||
"integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==",
|
"integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitest/utils": "3.2.4",
|
"@vitest/utils": "3.2.4",
|
||||||
"pathe": "^2.0.3",
|
"pathe": "^2.0.3",
|
||||||
@@ -3376,7 +3367,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
|
||||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"acorn": "bin/acorn"
|
"acorn": "bin/acorn"
|
||||||
},
|
},
|
||||||
@@ -4094,7 +4084,8 @@
|
|||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.4.3",
|
"version": "4.4.3",
|
||||||
@@ -4404,7 +4395,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"esbuild": "bin/esbuild"
|
"esbuild": "bin/esbuild"
|
||||||
},
|
},
|
||||||
@@ -4465,7 +4455,6 @@
|
|||||||
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
|
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@eslint-community/eslint-utils": "^4.8.0",
|
"@eslint-community/eslint-utils": "^4.8.0",
|
||||||
"@eslint-community/regexpp": "^4.12.1",
|
"@eslint-community/regexpp": "^4.12.1",
|
||||||
@@ -5672,7 +5661,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.11.7.tgz",
|
"resolved": "https://registry.npmjs.org/hono/-/hono-4.11.7.tgz",
|
||||||
"integrity": "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==",
|
"integrity": "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.9.0"
|
"node": ">=16.9.0"
|
||||||
}
|
}
|
||||||
@@ -8097,7 +8085,6 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoid": "^3.3.11",
|
"nanoid": "^3.3.11",
|
||||||
"picocolors": "^1.1.1",
|
"picocolors": "^1.1.1",
|
||||||
@@ -8231,7 +8218,6 @@
|
|||||||
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
|
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"prettier": "bin/prettier.cjs"
|
"prettier": "bin/prettier.cjs"
|
||||||
},
|
},
|
||||||
@@ -8248,7 +8234,6 @@
|
|||||||
"integrity": "sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ==",
|
"integrity": "sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"prettier": "^3.0.0",
|
"prettier": "^3.0.0",
|
||||||
"svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0"
|
"svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0"
|
||||||
@@ -8480,7 +8465,6 @@
|
|||||||
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
|
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@@ -8491,7 +8475,6 @@
|
|||||||
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
|
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"scheduler": "^0.26.0"
|
"scheduler": "^0.26.0"
|
||||||
},
|
},
|
||||||
@@ -8766,7 +8749,6 @@
|
|||||||
"integrity": "sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==",
|
"integrity": "sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "1.0.8"
|
"@types/estree": "1.0.8"
|
||||||
},
|
},
|
||||||
@@ -8877,7 +8859,6 @@
|
|||||||
"integrity": "sha512-elOcIZRTM76dvxNAjqYrucTSI0teAF/L2Lv0s6f6b7FOwcwIuA357bIE871580AjHJuSvLIRUosgV+lIWx6Rgg==",
|
"integrity": "sha512-elOcIZRTM76dvxNAjqYrucTSI0teAF/L2Lv0s6f6b7FOwcwIuA357bIE871580AjHJuSvLIRUosgV+lIWx6Rgg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chokidar": "^4.0.0",
|
"chokidar": "^4.0.0",
|
||||||
"immutable": "^5.0.2",
|
"immutable": "^5.0.2",
|
||||||
@@ -9172,7 +9153,6 @@
|
|||||||
"integrity": "sha512-LwF0VZsT4qkgx66Ad/q0QgZZrU2a5WftaADDEcJ3bGq3O2fHvwWPlSZjM1HiXD4vqP9U5JiMqQkV1gkyH0XJkw==",
|
"integrity": "sha512-LwF0VZsT4qkgx66Ad/q0QgZZrU2a5WftaADDEcJ3bGq3O2fHvwWPlSZjM1HiXD4vqP9U5JiMqQkV1gkyH0XJkw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@storybook/global": "^5.0.0",
|
"@storybook/global": "^5.0.0",
|
||||||
"@storybook/icons": "^2.0.1",
|
"@storybook/icons": "^2.0.1",
|
||||||
@@ -9387,7 +9367,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.48.3.tgz",
|
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.48.3.tgz",
|
||||||
"integrity": "sha512-w7QZ398cdNherTdiQ/v3SYLLGOO4948Jgjh04PYqtTYVohmBvbmFwLmo7pp8gp4/1tceRWfSTjHgjtfpCVNJmQ==",
|
"integrity": "sha512-w7QZ398cdNherTdiQ/v3SYLLGOO4948Jgjh04PYqtTYVohmBvbmFwLmo7pp8gp4/1tceRWfSTjHgjtfpCVNJmQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/remapping": "^2.3.4",
|
"@jridgewell/remapping": "^2.3.4",
|
||||||
"@jridgewell/sourcemap-codec": "^1.5.0",
|
"@jridgewell/sourcemap-codec": "^1.5.0",
|
||||||
@@ -9633,7 +9612,6 @@
|
|||||||
"integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==",
|
"integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "github",
|
"type": "github",
|
||||||
"url": "https://github.com/sponsors/dcastil"
|
"url": "https://github.com/sponsors/dcastil"
|
||||||
@@ -9664,8 +9642,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz",
|
||||||
"integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==",
|
"integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/tapable": {
|
"node_modules/tapable": {
|
||||||
"version": "2.2.2",
|
"version": "2.2.2",
|
||||||
@@ -9942,7 +9919,6 @@
|
|||||||
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
|
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"peer": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
@@ -10336,7 +10312,6 @@
|
|||||||
"integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==",
|
"integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
"fdir": "^6.5.0",
|
"fdir": "^6.5.0",
|
||||||
@@ -10497,7 +10472,6 @@
|
|||||||
"integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==",
|
"integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/chai": "^5.2.2",
|
"@types/chai": "^5.2.2",
|
||||||
"@vitest/expect": "3.2.4",
|
"@vitest/expect": "3.2.4",
|
||||||
@@ -10819,7 +10793,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/zod/-/zod-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/zod/-/zod-4.2.1.tgz",
|
||||||
"integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==",
|
"integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
import { parseHeadersToArray, serializeHeaders } from '$lib/utils';
|
import { parseHeadersToArray, serializeHeaders } from '$lib/utils';
|
||||||
import { UrlProtocol } from '$lib/enums';
|
import { UrlProtocol } from '$lib/enums';
|
||||||
import { MCP_SERVER_URL_PLACEHOLDER } from '$lib/constants';
|
import { MCP_SERVER_URL_PLACEHOLDER } from '$lib/constants';
|
||||||
|
import { mcpStore } from '$lib/stores/mcp.svelte';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
url: string;
|
url: string;
|
||||||
@@ -62,14 +63,33 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if !isWebSocket && onUseProxyChange}
|
{#if !isWebSocket && onUseProxyChange}
|
||||||
<label class="mt-3 flex cursor-pointer items-center gap-2">
|
<label
|
||||||
|
class="mt-3 flex items-start gap-2"
|
||||||
|
class:cursor-pointer={mcpStore.isProxyAvailable}
|
||||||
|
class:opacity-80={!mcpStore.isProxyAvailable}
|
||||||
|
>
|
||||||
<Switch
|
<Switch
|
||||||
|
class="mt-1"
|
||||||
id="use-proxy-{id}"
|
id="use-proxy-{id}"
|
||||||
checked={useProxy}
|
checked={useProxy}
|
||||||
|
disabled={!mcpStore.isProxyAvailable}
|
||||||
onCheckedChange={(checked) => onUseProxyChange?.(checked)}
|
onCheckedChange={(checked) => onUseProxyChange?.(checked)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<span class="text-xs text-muted-foreground">Use llama-server proxy</span>
|
<span>
|
||||||
|
<span class="text-xs text-muted-foreground">Use llama-server proxy</span>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
{#if !mcpStore.isProxyAvailable}
|
||||||
|
<span class="inline-flex gap-0.75 text-xs text-muted-foreground/60"
|
||||||
|
>(Run <pre>llama-server</pre>
|
||||||
|
with
|
||||||
|
<pre>--webui-mcp-proxy</pre>
|
||||||
|
flag)</span
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
</label>
|
</label>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { browser } from '$app/environment';
|
import { browser } from '$app/environment';
|
||||||
|
import { base } from '$app/paths';
|
||||||
import { MCPService } from '$lib/services/mcp.service';
|
import { MCPService } from '$lib/services/mcp.service';
|
||||||
import { config, settingsStore } from '$lib/stores/settings.svelte';
|
import { config, settingsStore } from '$lib/stores/settings.svelte';
|
||||||
import { mcpResourceStore } from '$lib/stores/mcp-resources.svelte';
|
import { mcpResourceStore } from '$lib/stores/mcp-resources.svelte';
|
||||||
@@ -42,6 +43,7 @@ import {
|
|||||||
ToolCallType
|
ToolCallType
|
||||||
} from '$lib/enums';
|
} from '$lib/enums';
|
||||||
import {
|
import {
|
||||||
|
CORS_PROXY_ENDPOINT,
|
||||||
DEFAULT_CACHE_TTL_MS,
|
DEFAULT_CACHE_TTL_MS,
|
||||||
DEFAULT_MCP_CONFIG,
|
DEFAULT_MCP_CONFIG,
|
||||||
EXPECTED_THEMED_ICON_PAIR_COUNT,
|
EXPECTED_THEMED_ICON_PAIR_COUNT,
|
||||||
@@ -78,165 +80,13 @@ import type { ListChangedHandlers } from '@modelcontextprotocol/sdk/types.js';
|
|||||||
import type { DatabaseMessageExtraMcpResource, McpServerOverride } from '$lib/types/database';
|
import type { DatabaseMessageExtraMcpResource, McpServerOverride } from '$lib/types/database';
|
||||||
import type { SettingsConfigType } from '$lib/types/settings';
|
import type { SettingsConfigType } from '$lib/types/settings';
|
||||||
|
|
||||||
export function buildMcpClientConfig(
|
|
||||||
cfg: SettingsConfigType,
|
|
||||||
perChatOverrides?: McpServerOverride[]
|
|
||||||
): MCPClientConfig | undefined {
|
|
||||||
return buildMcpClientConfigInternal(cfg, perChatOverrides);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal helper to build MCP client config.
|
|
||||||
* Kept as standalone function for external use and tests.
|
|
||||||
*/
|
|
||||||
export function buildMcpClientConfigInternal(
|
|
||||||
cfg: SettingsConfigType,
|
|
||||||
perChatOverrides?: McpServerOverride[]
|
|
||||||
): MCPClientConfig | undefined {
|
|
||||||
const rawServers = parseServerSettings(cfg.mcpServers);
|
|
||||||
if (!rawServers.length) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
const servers: Record<string, MCPServerConfig> = {};
|
|
||||||
|
|
||||||
for (const [index, entry] of rawServers.entries()) {
|
|
||||||
if (!checkServerEnabled(entry, perChatOverrides)) continue;
|
|
||||||
const normalized = buildServerConfig(entry);
|
|
||||||
if (normalized) servers[generateMcpServerId(entry.id, index)] = normalized;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Object.keys(servers).length === 0) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
protocolVersion: DEFAULT_MCP_CONFIG.protocolVersion,
|
|
||||||
capabilities: DEFAULT_MCP_CONFIG.capabilities,
|
|
||||||
clientInfo: DEFAULT_MCP_CONFIG.clientInfo,
|
|
||||||
requestTimeoutMs: Math.round(DEFAULT_MCP_CONFIG.requestTimeoutSeconds * 1000),
|
|
||||||
servers
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a unique server ID from an optional ID string or index.
|
|
||||||
* @deprecated Use MCPStore.#generateServerId instead
|
|
||||||
*/
|
|
||||||
function generateMcpServerId(id: unknown, index: number): string {
|
|
||||||
if (typeof id === 'string' && id.trim()) {
|
|
||||||
return id.trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
return `${MCP_SERVER_ID_PREFIX}-${index + 1}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses raw server settings from config into MCPServerSettingsEntry array.
|
|
||||||
* @deprecated Use MCPStore.#parseServerSettings instead
|
|
||||||
*/
|
|
||||||
function parseServerSettings(rawServers: unknown): MCPServerSettingsEntry[] {
|
|
||||||
if (!rawServers) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
let parsed: unknown;
|
|
||||||
if (typeof rawServers === 'string') {
|
|
||||||
const trimmed = rawServers.trim();
|
|
||||||
if (!trimmed) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
parsed = JSON.parse(trimmed);
|
|
||||||
} catch (error) {
|
|
||||||
console.warn('[MCP] Failed to parse mcpServers JSON:', error);
|
|
||||||
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
parsed = rawServers;
|
|
||||||
}
|
|
||||||
if (!Array.isArray(parsed)) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return parsed.map((entry, index) => {
|
|
||||||
const url = typeof entry?.url === 'string' ? entry.url.trim() : '';
|
|
||||||
const headers = typeof entry?.headers === 'string' ? entry.headers.trim() : undefined;
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: generateMcpServerId((entry as { id?: unknown })?.id, index),
|
|
||||||
enabled: Boolean((entry as { enabled?: unknown })?.enabled),
|
|
||||||
url,
|
|
||||||
name: (entry as { name?: string })?.name,
|
|
||||||
requestTimeoutSeconds: DEFAULT_MCP_CONFIG.requestTimeoutSeconds,
|
|
||||||
headers: headers || undefined,
|
|
||||||
useProxy: Boolean((entry as { useProxy?: unknown })?.useProxy)
|
|
||||||
} satisfies MCPServerSettingsEntry;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds server configuration from a settings entry.
|
|
||||||
* @deprecated Use MCPStore.#buildServerConfig instead
|
|
||||||
*/
|
|
||||||
function buildServerConfig(
|
|
||||||
entry: MCPServerSettingsEntry,
|
|
||||||
connectionTimeoutMs = DEFAULT_MCP_CONFIG.connectionTimeoutMs
|
|
||||||
): MCPServerConfig | undefined {
|
|
||||||
if (!entry?.url) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
let headers: Record<string, string> | undefined;
|
|
||||||
if (entry.headers) {
|
|
||||||
try {
|
|
||||||
const parsed = JSON.parse(entry.headers);
|
|
||||||
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed))
|
|
||||||
headers = parsed as Record<string, string>;
|
|
||||||
} catch {
|
|
||||||
console.warn('[MCP] Failed to parse custom headers JSON:', entry.headers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
url: entry.url,
|
|
||||||
transport: detectMcpTransportFromUrl(entry.url),
|
|
||||||
handshakeTimeoutMs: connectionTimeoutMs,
|
|
||||||
requestTimeoutMs: Math.round(entry.requestTimeoutSeconds * 1000),
|
|
||||||
headers,
|
|
||||||
useProxy: entry.useProxy
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a server is enabled, considering per-chat overrides.
|
|
||||||
* @deprecated Use MCPStore.#checkServerEnabled instead
|
|
||||||
*/
|
|
||||||
function checkServerEnabled(
|
|
||||||
server: MCPServerSettingsEntry,
|
|
||||||
perChatOverrides?: McpServerOverride[]
|
|
||||||
): boolean {
|
|
||||||
if (!server.enabled) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (perChatOverrides) {
|
|
||||||
const override = perChatOverrides.find((o) => o.serverId === server.id);
|
|
||||||
|
|
||||||
return override?.enabled ?? false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
class MCPStore {
|
class MCPStore {
|
||||||
private _isInitializing = $state(false);
|
private _isInitializing = $state(false);
|
||||||
private _error = $state<string | null>(null);
|
private _error = $state<string | null>(null);
|
||||||
private _toolCount = $state(0);
|
private _toolCount = $state(0);
|
||||||
private _connectedServers = $state<string[]>([]);
|
private _connectedServers = $state<string[]>([]);
|
||||||
private _healthChecks = $state<Record<string, HealthCheckState>>({});
|
private _healthChecks = $state<Record<string, HealthCheckState>>({});
|
||||||
|
private _proxyAvailable = $state(false);
|
||||||
|
|
||||||
private connections = new Map<string, MCPConnection>();
|
private connections = new Map<string, MCPConnection>();
|
||||||
private toolsIndex = new Map<string, string>();
|
private toolsIndex = new Map<string, string>();
|
||||||
@@ -246,6 +96,29 @@ class MCPStore {
|
|||||||
private initPromise: Promise<boolean> | null = null;
|
private initPromise: Promise<boolean> | null = null;
|
||||||
private activeFlowCount = 0;
|
private activeFlowCount = 0;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
if (browser) {
|
||||||
|
this.probeProxy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Probes the CORS proxy endpoint to determine availability.
|
||||||
|
* The endpoint is only registered when llama-server runs with --webui-mcp-proxy.
|
||||||
|
*/
|
||||||
|
async probeProxy(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${base}${CORS_PROXY_ENDPOINT}`, { method: 'HEAD' });
|
||||||
|
this._proxyAvailable = response.status !== 404;
|
||||||
|
} catch {
|
||||||
|
this._proxyAvailable = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get isProxyAvailable(): boolean {
|
||||||
|
return this._proxyAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a unique server ID from an optional ID string or index.
|
* Generates a unique server ID from an optional ID string or index.
|
||||||
*/
|
*/
|
||||||
@@ -520,6 +393,7 @@ class MCPStore {
|
|||||||
|
|
||||||
getServerLabel(server: MCPServerSettingsEntry): string {
|
getServerLabel(server: MCPServerSettingsEntry): string {
|
||||||
const healthState = this.getHealthCheckState(server.id);
|
const healthState = this.getHealthCheckState(server.id);
|
||||||
|
|
||||||
if (healthState?.status === HealthCheckStatus.SUCCESS)
|
if (healthState?.status === HealthCheckStatus.SUCCESS)
|
||||||
return (
|
return (
|
||||||
healthState.serverInfo?.title || healthState.serverInfo?.name || server.name || server.url
|
healthState.serverInfo?.title || healthState.serverInfo?.name || server.name || server.url
|
||||||
@@ -603,6 +477,7 @@ class MCPStore {
|
|||||||
*/
|
*/
|
||||||
#proxyIconSrc(src: string): string {
|
#proxyIconSrc(src: string): string {
|
||||||
if (src.startsWith('data:')) return src;
|
if (src.startsWith('data:')) return src;
|
||||||
|
if (!this._proxyAvailable) return src;
|
||||||
|
|
||||||
return getProxiedUrlString(src);
|
return getProxiedUrlString(src);
|
||||||
}
|
}
|
||||||
@@ -629,7 +504,7 @@ class MCPStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return getFaviconUrl(server.url);
|
return getFaviconUrl(server.url, this._proxyAvailable);
|
||||||
}
|
}
|
||||||
|
|
||||||
isAnyServerLoading(): boolean {
|
isAnyServerLoading(): boolean {
|
||||||
@@ -2072,6 +1947,7 @@ export const mcpIsInitializing = () => mcpStore.isInitializing;
|
|||||||
export const mcpIsInitialized = () => mcpStore.isInitialized;
|
export const mcpIsInitialized = () => mcpStore.isInitialized;
|
||||||
export const mcpError = () => mcpStore.error;
|
export const mcpError = () => mcpStore.error;
|
||||||
export const mcpIsEnabled = () => mcpStore.isEnabled;
|
export const mcpIsEnabled = () => mcpStore.isEnabled;
|
||||||
|
export const mcpIsProxyAvailable = () => mcpStore.isProxyAvailable;
|
||||||
export const mcpAvailableTools = () => mcpStore.availableTools;
|
export const mcpAvailableTools = () => mcpStore.availableTools;
|
||||||
export const mcpConnectedServerCount = () => mcpStore.connectedServerCount;
|
export const mcpConnectedServerCount = () => mcpStore.connectedServerCount;
|
||||||
export const mcpConnectedServerNames = () => mcpStore.connectedServerNames;
|
export const mcpConnectedServerNames = () => mcpStore.connectedServerNames;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
* @param urlString - The URL to get the favicon for
|
* @param urlString - The URL to get the favicon for
|
||||||
* @returns The favicon URL or null if invalid
|
* @returns The favicon URL or null if invalid
|
||||||
*/
|
*/
|
||||||
export function getFaviconUrl(urlString: string): string | null {
|
export function getFaviconUrl(urlString: string, useProxy = true): string | null {
|
||||||
try {
|
try {
|
||||||
const url = new URL(urlString);
|
const url = new URL(urlString);
|
||||||
const hostnameParts = url.hostname.split(DOMAIN_SEPARATOR);
|
const hostnameParts = url.hostname.split(DOMAIN_SEPARATOR);
|
||||||
@@ -27,7 +27,7 @@ export function getFaviconUrl(urlString: string): string | null {
|
|||||||
: url.hostname;
|
: url.hostname;
|
||||||
|
|
||||||
const googleFaviconUrl = `${GOOGLE_FAVICON_BASE_URL}?domain=${rootDomain}&sz=${DEFAULT_FAVICON_SIZE}`;
|
const googleFaviconUrl = `${GOOGLE_FAVICON_BASE_URL}?domain=${rootDomain}&sz=${DEFAULT_FAVICON_SIZE}`;
|
||||||
return getProxiedUrlString(googleFaviconUrl);
|
return useProxy ? getProxiedUrlString(googleFaviconUrl) : googleFaviconUrl;
|
||||||
} catch {
|
} catch {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -231,7 +231,7 @@
|
|||||||
<Sidebar.Trigger
|
<Sidebar.Trigger
|
||||||
class="transition-left absolute left-0 z-[900] duration-200 ease-linear {sidebarOpen
|
class="transition-left absolute left-0 z-[900] duration-200 ease-linear {sidebarOpen
|
||||||
? 'md:left-[var(--sidebar-width)]'
|
? 'md:left-[var(--sidebar-width)]'
|
||||||
: ''}"
|
: 'md:left-0!'}"
|
||||||
style="translate: 1rem 1rem;"
|
style="translate: 1rem 1rem;"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user