diff --git a/mcp-auth/=0.30.0 b/mcp-auth/=0.30.0 new file mode 100644 index 0000000..1041229 --- /dev/null +++ b/mcp-auth/=0.30.0 @@ -0,0 +1,20 @@ +error: externally-managed-environment + +× This environment is externally managed +╰─> To install Python packages system-wide, try apt install + python3-xyz, where xyz is the package you are trying to + install. + + If you wish to install a non-Debian-packaged Python package, + create a virtual environment using python3 -m venv path/to/venv. + Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make + sure you have python3-full installed. + + If you wish to install a non-Debian packaged Python application, + it may be easiest to use pipx install xyz, which will manage a + virtual environment for you. Make sure you have pipx installed. + + See /usr/share/doc/python3.12/README.venv for more information. + +note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages. +hint: See PEP 668 for the detailed specification. diff --git a/mcp-auth/backend/Dockerfile b/mcp-auth/backend/Dockerfile index b40bd4e..ccd9d69 100644 --- a/mcp-auth/backend/Dockerfile +++ b/mcp-auth/backend/Dockerfile @@ -6,7 +6,9 @@ WORKDIR /app # 依赖单独成层,利用缓存 COPY requirements.txt ./requirements.txt -RUN pip install --no-cache-dir -r requirements.txt +RUN pip install --no-cache-dir --timeout 120 --retries 5 \ + -i https://pypi.tuna.tsinghua.edu.cn/simple \ + -r requirements.txt # 后端源码 COPY app ./app diff --git a/mcp-auth/backend/app/core/config.py b/mcp-auth/backend/app/core/config.py index 2d93158..4475ec5 100644 --- a/mcp-auth/backend/app/core/config.py +++ b/mcp-auth/backend/app/core/config.py @@ -29,5 +29,9 @@ class Settings: REDIS_DB: int = int(os.getenv("REDIS_DB", "0")) REDIS_PASSWORD: str = os.getenv("REDIS_PASSWORD", "digiwin") + # 反向代理路径前缀(让 Swagger / OpenAPI 在带前缀的代理后正确生成 URL) + # 生产经外层 nginx 暴露在 https:///mcp-auth-api/ 下时设为 /mcp-auth-api;直连 8003 时留空 + ROOT_PATH: str = os.getenv("ROOT_PATH", "") + settings = Settings() diff --git a/mcp-auth/backend/app/main.py b/mcp-auth/backend/app/main.py index f534c16..8ca7c2c 100644 --- a/mcp-auth/backend/app/main.py +++ b/mcp-auth/backend/app/main.py @@ -32,6 +32,9 @@ app = FastAPI( title="MCP Auth Admin", description="MCP 服务 Bearer Token 动态鉴权管理后台", version="1.0.0", + # 反向代理路径前缀:带前缀的外层 nginx(如 /mcp-auth-api)后, + # OpenAPI servers 与 Swagger 加载的 openapi.json 会带上该前缀,文档才能正确渲染 + root_path=settings.ROOT_PATH, lifespan=lifespan, ) diff --git a/mcp-auth/backend/docker-compose.yml b/mcp-auth/backend/docker-compose.yml index 6619f47..c2b7878 100644 --- a/mcp-auth/backend/docker-compose.yml +++ b/mcp-auth/backend/docker-compose.yml @@ -25,4 +25,6 @@ services: - REDIS_PORT=${REDIS_PORT:-6379} - REDIS_DB=${REDIS_DB:-0} - REDIS_PASSWORD=${REDIS_PASSWORD:-digiwin} + # 外层反向代理路径前缀(/mcp-auth-api/docs 文档正常渲染所需) + - ROOT_PATH=${ROOT_PATH:-/mcp-auth-api} restart: unless-stopped diff --git a/mcp-auth/frontend/nginx.conf b/mcp-auth/frontend/nginx.conf index 58cb37a..4a325a1 100644 --- a/mcp-auth/frontend/nginx.conf +++ b/mcp-auth/frontend/nginx.conf @@ -10,6 +10,54 @@ server { gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript image/svg+xml; gzip_min_length 256; + # ── /mcp-admin 子路径(外部 nginx 不剥离前缀,需在此处理)── + + # 后端 API 反向代理(/mcp-admin/api/ → 后端 /api/) + location /mcp-admin/api/ { + proxy_pass ${BACKEND_URL}/api/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + add_header Cache-Control "no-cache, no-store, must-revalidate" always; + add_header Pragma "no-cache" always; + } + + # 健康检查 + location /mcp-admin/health { + proxy_pass ${BACKEND_URL}/api/health; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } + + # 鼎捷云 IAM 登录服务反向代理(/mcp-admin/iam-api/ → iam.digiwincloud.com.cn/) + location /mcp-admin/iam-api/ { + proxy_pass https://iam.digiwincloud.com.cn/; + proxy_set_header Host iam.digiwincloud.com.cn; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_ssl_server_name on; + + add_header Cache-Control "no-cache, no-store, must-revalidate" always; + add_header Pragma "no-cache" always; + } + + # 静态资源长缓存(Vite 构建产物带 hash,/mcp-admin/assets/ → /assets/) + location /mcp-admin/assets/ { + alias /usr/share/nginx/html/assets/; + expires 1y; + add_header Cache-Control "public, immutable"; + } + + # SPA 路由 fallback:/mcp-admin 下的非文件请求回退到 index.html + location /mcp-admin/ { + try_files $uri $uri/ /index.html; + } + + # ── 根路径(直接访问容器时使用)── + # 后端 API 反向代理 location /api/ { proxy_pass ${BACKEND_URL}/api/; @@ -18,7 +66,6 @@ server { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; - # 禁止浏览器缓存 API 响应 add_header Cache-Control "no-cache, no-store, must-revalidate" always; add_header Pragma "no-cache" always; } @@ -30,7 +77,7 @@ server { proxy_set_header X-Real-IP $remote_addr; } - # 鼎捷云 IAM 登录服务反向代理(与 vite.config.ts 中 /iam-api 代理一致) + # 鼎捷云 IAM 登录服务反向代理 location /iam-api/ { proxy_pass https://iam.digiwincloud.com.cn/; proxy_set_header Host iam.digiwincloud.com.cn; @@ -39,17 +86,11 @@ server { proxy_set_header X-Forwarded-Proto $scheme; proxy_ssl_server_name on; - # 禁止浏览器缓存 API 响应 add_header Cache-Control "no-cache, no-store, must-revalidate" always; add_header Pragma "no-cache" always; } - # SPA 路由 fallback:所有非文件请求回退到 index.html - location / { - try_files $uri $uri/ /index.html; - } - - # 静态资源长缓存(Vite 构建产物带 hash) + # 静态资源长缓存 location /assets/ { expires 1y; add_header Cache-Control "public, immutable"; @@ -60,4 +101,9 @@ server { expires 30d; add_header Cache-Control "public"; } + + # SPA 路由 fallback + location / { + try_files $uri $uri/ /index.html; + } } diff --git a/mcp-auth/frontend/src/api/client.ts b/mcp-auth/frontend/src/api/client.ts index 4743f41..adc9a01 100644 --- a/mcp-auth/frontend/src/api/client.ts +++ b/mcp-auth/frontend/src/api/client.ts @@ -2,7 +2,7 @@ import axios from 'axios'; import { APP_TOKEN } from '../services/iamAuth'; const api = axios.create({ - baseURL: '/api', + baseURL: `${import.meta.env.BASE_URL}api`, timeout: 15000, }); @@ -22,10 +22,10 @@ api.interceptors.response.use( (err) => { if (err.response?.status === 401) { const path = window.location.pathname; - if (path !== '/login' && !path.startsWith('/sso-login')) { + if (path !== `${import.meta.env.BASE_URL}login` && !path.startsWith(`${import.meta.env.BASE_URL}sso-login`)) { sessionStorage.removeItem('userToken'); sessionStorage.removeItem('userInfo'); - window.location.href = '/login'; + window.location.href = `${import.meta.env.BASE_URL}login`; } } return Promise.reject(err); diff --git a/mcp-auth/frontend/src/main.tsx b/mcp-auth/frontend/src/main.tsx index 9930b41..7849d1c 100644 --- a/mcp-auth/frontend/src/main.tsx +++ b/mcp-auth/frontend/src/main.tsx @@ -9,7 +9,7 @@ import 'antd/dist/reset.css'; ReactDOM.createRoot(document.getElementById('root')!).render( - + diff --git a/mcp-auth/frontend/src/services/iamAuth.ts b/mcp-auth/frontend/src/services/iamAuth.ts index 0294df0..e2c9d5b 100644 --- a/mcp-auth/frontend/src/services/iamAuth.ts +++ b/mcp-auth/frontend/src/services/iamAuth.ts @@ -13,7 +13,7 @@ import { JSEncrypt } from 'jsencrypt'; */ // 代理路径(vite.config.ts 中 /iam-api → https://iam.digiwincloud.com.cn) -const IAM_API_BASE = '/iam-api/api/iam/v2'; +const IAM_API_BASE = `${import.meta.env.BASE_URL}iam-api/api/iam/v2`; const IAM_IDENTITY_BASE = `${IAM_API_BASE}/identity`; // 应用 apptoken(digi-middleware-auth-app) diff --git a/mcp-auth/frontend/vite.config.ts b/mcp-auth/frontend/vite.config.ts index 58e8a2e..e3c2cda 100644 --- a/mcp-auth/frontend/vite.config.ts +++ b/mcp-auth/frontend/vite.config.ts @@ -3,15 +3,21 @@ import react from '@vitejs/plugin-react' export default defineConfig({ plugins: [react()], + base: '/mcp-admin/', server: { port: 5173, proxy: { - '/api': 'https://ai-workshop.digiwincloud.com.cn/mcp-auth-api', + // 生产部署在 /mcp-admin 子路径下,dev 代理路径也需带前缀 + '/mcp-admin/api': { + target: 'https://ai-workshop.digiwincloud.com.cn/mcp-auth-api', + changeOrigin: true, + rewrite: (p) => p.replace(/^\/mcp-admin/, ''), + }, // 鼎捷云 IAM 登录服务代理(避免 CORS / 网络问题) - '/iam-api': { + '/mcp-admin/iam-api': { target: 'https://iam.digiwincloud.com.cn', changeOrigin: true, - rewrite: (p) => p.replace(/^\/iam-api/, ''), + rewrite: (p) => p.replace(/^\/mcp-admin\/iam-api/, ''), }, }, },