主题
04|本地部署实证:模型 / Skill / MCP 三大市场能力建设
一句话:本地三大市场跑通证明的是“控制面语义”:Model、Skill、MCP 一律收敛到 Product 这一个主体,Nacos 一次导入 174 个 Skill 与 186 个 Worker,发布与订阅到 Portal 全链可复现;没证明的是数据面——Higress 缺席使真实调用、工具发现、限流计量全部落空,17 个公开端点还能匿名读版本与文件树,订阅 APPROVED 距一次可用调用隔着整条网关与凭证中介。
定位:06 专栏第一轮运行时实证。目标不是"装起来看看",而是按 00 总纲的三大市场能力建设要求,把模型市场、Skill 市场、MCP 市场的目录、发布与订阅链路在本地走通,并沉淀可复用的 API 调用序列与台账;数据面调用不在本轮范围。
状态:✅ 产品目录与订阅链实测通过(2026-10-25,Windows + Docker Desktop);⏳ 数据面调用、计量、OIDC 尚未闭环。本文是 POC 记录,不是生产部署指南。
一、部署形态与拓扑
按本次实证范围(“关注 HiMarket 对 Skill、MCP 的落地 + 模型配置”),本环境只起 HiMarket 最小集,不装 Higress(网关出口环节后置)。因此不能据此声称“发布→调用→计量”已闭环。
容器清单与端口(docker ps 实测):
| 容器 | 镜像 | 端口映射 | 健康状态 |
|---|---|---|---|
| himarket-mysql | higress-group/mysql:latest (8.0.32) | 0.0.0.0:3306 | healthy |
| nacos-standalone | nacos-server:v3.2.1-2026.03.30 | 8080/8848/9848 | ready |
| docker-himarket-server-1 | higress-group/himarket-server:latest | 8081→8080 | healthy |
| docker-himarket-admin-1 | higress-group/himarket-admin:latest | 5174→8000 | healthy |
| docker-himarket-frontend-1 | higress-group/himarket-frontend:latest | 5173→8000 | healthy |
| sandbox-shared | higress-group/sandbox:latest | 8080 | up |
环境基线:Docker 29.8.1;agentscope-service 全套、qwenpaw、旧 higress-ai-gateway 已全部停止(端口腾空)。
凭据来自部署 env(himarket-install-docker.env),不得写入文档、Git 或截图:
| 角色 | 用户名 | 密码 |
|---|---|---|
| HiMarket 管理员 | <admin-user> | <from-secret-store> |
| Portal 门户用户 | <portal-user> | <from-secret-store> |
| Nacos 管理员 | <nacos-user> | <from-secret-store> |
| MySQL 应用账号 | <db-user> | <from-secret-store> |
生产环境应使用 Vault/KMS 或 K8s Secret 管理,禁止 root 账号直连应用;本地实验口令如已暴露,应视为失效并轮换。
二、三大市场能力实证(API 级,全部实测)
2.1 模型市场:MODEL_API 产品供给侧 + 订阅
① 创建模型产品(POST /products,管理面,8081)
http
POST http://localhost:8081/products
Authorization: Bearer <admin-token>
Content-Type: application/json
{
"name": "TokenPlan Qwen Max",
"description": "企业统一模型接入(token-plan 网关,OpenAI 兼容)qwen-max",
"type": "MODEL_API",
"feature": {
"modelFeature": {
"model": "qwen-max",
"maxTokens": 8192,
"temperature": 0.7,
"streaming": true,
"webSearch": false,
"enableThinking": true,
"enableMultiModal": false
}
}
}响应:code=SUCCESS,productId=product-c6e84aa389854719baf465b306a89ebc。
② 验证类型目录:GET /products?type=MODEL_API → total=1(TokenPlan Qwen Max)。
模型 Key 只在 Runtime Secret 中读取;文档只记录变量名,不记录密钥片段。模型调用仍未经过 Higress,因此本节的“订阅成功”不能证明数据面可用。
③ 发布到 Portal:POST /products/{id}/publications body {"portalId":"portal-..."} → OK。
④ 订阅(消费侧):见 2.5 订阅链,模型产品订阅 status=APPROVED。
2.2 Skill 市场:Nacos 导入 + 消费侧
① 登记 Nacos 实例(运营面,5174 代理):
http
POST http://localhost:5174/api/v1/nacos
{
"nacosName": "default-nacos",
"serverUrl": "http://nacos:8848",
"username": "<nacos-user>",
"password": "<from-secret-store>",
"description": "Built-in Nacos instance"
}GET /api/v1/nacos → nacosId=nacos-ac8bc042783d4e379e066da332bfed71(isDefault=true)。
② 从 Nacos 导入 Skills(POST /skills/import,即 POST /api/v1/skills/import?nacosId=...&namespace=public):
http
POST http://localhost:5174/api/v1/skills/import?nacosId=nacos-ac8bc042783d4e379e066da332bfed71&namespace=public③ 结果确认:GET /products?type=AGENT_SKILL(8081,admin)→ total=174,产品为品牌规范类英文 slug(brand-guidelines、nacos-skill-registry、algorithmic-art 等),每个产品 skillConfig.nacosId 关联登记的 Nacos 实例。
④ Skill 消费侧端点(源码级确认):
GET /skills/{productId}/cli-info—— CLI 下载信息GET /skills/{productId}/versions、GET /skills/{productId}/files/**—— 版本/文件树,当前为@PublicAccessGET /skills/{productId}/download—— 包 ZIP 下载;不在@PublicAccess列表,需走默认认证链- 每 5 分钟
SkillWorkerMetadataSyncTask自动同步 Nacos 元数据
安全校正:Skill 文件与版本元数据可公开读,是当前源码行为,不应直接视为生产策略。生产需按“已发布 + 已订阅”限制下载与文件访问,并对包做签名、扫描和来源校验。
2.3 Worker 市场(附赠):Nacos 导入
POST /api/v1/workers/import?nacosId=...&namespace=public → GET /products?type=WORKER → total=186,产品为专家角色型(叙事学家、历史学家、应付账款智能体、身份信任架构师等),workerConfig.nacosId 已关联。
360 = 174 AGENT_SKILL + 186 WORKER——镜像预置仅含 Skill/Worker 两类,模型与 MCP 产品为本轮补建。
2.4 MCP 市场:MCP_SERVER 产品 + 元数据 + 消费侧
① 创建 MCP 产品:POST /products(8081)type=MCP_SERVER → product-e919424eb2084cab881b3578989f362d。
② 保存 MCP 元数据(POST /mcp-servers/meta,管理面):
http
POST http://localhost:8081/mcp-servers/meta
{
"productId": "product-e919424eb2084cab881b3578989f362d",
"mcpName": "enterprise-internal-mcp",
"displayName": "企业内部 MCP 服务",
"description": "企业内网 MCP Server(streamable_http),统一凭证由平台注入",
"protocolType": "streamable_http",
"connectionConfig": "{\"url\":\"http://mcp-internal.example.com/mcp\",\"transport\":\"streamable_http\"}",
"sourceType": "MANUAL",
"visibility": "PUBLIC"
}响应:code=SUCCESS,mcpServerId=mcp-7d648075c83842098f857eaba036aa5b。
③ 消费侧查询:GET /mcp-servers/meta?productId=... → 返回 McpMetaResult;当前 sanitize() 只清空 subscribeParams,不会替你清理 connectionConfig 中的任意敏感字段。因此上游密钥绝不能写入 connectionConfig,必须由 Vault/KMS 保存并由 Broker 在调用时注入。
④ MCP 相关端点(源码级):POST /mcp-servers/endpoints、POST /mcp-servers/meta/{id}/refresh-tools(工具元数据同步)、POST /mcp-servers/meta/{id}/deploy-sandbox(沙箱托管)、GET /mcp-servers/meta/batch/public(PublicAccess 批量);McpConfigResult.toTransportConfig() 生成标准 MCP 连接描述。
2.5 订阅链贯通(控制面:Portal → 开发者 → Consumer → 订阅)
实测记录:
POST /api/v1/portals{"name":"demo"}→portal-78f54d2af4e142bfaa9c9d4cdb310969(autoApproveSubscriptions=true)POST /api/v1/developers{"username":"<portal-user>","password":"<from-secret-store>"}→ dev-47ec96c1983d4dc29ad4f2dcf5ec60a9(PENDING)PATCH /developers/{devId}/status{"portalId":"...","status":"APPROVED"}→ OKPOST /developers/login→ consumer-ebeeacf4ae6d46489bd6d7de61e81afbPOST /consumers/{id}/subscriptions{"productId":"..."}:- 模型产品 →
subscription-42e6d4a5f2fb4de585a856338f0a3056APPROVED - MCP 产品 →
subscription-f2653a5ebbd949b98b991ef1bde54915APPROVED
- 模型产品 →
GET /consumers/{id}/subscriptions→ total=2(两条均 APPROVED)
三、关键架构认知(本轮实证修正)
- 市场模型 = Product 统一主体:Skill / Worker / MCP / Model 都是
ProductType枚举(AGENT_SKILL/WORKER/MCP_SERVER/MODEL_API)下的产品类型;市场列表统一走/products?type=xxx,/skills、/workers、/mcp-servers只有子资源方法(下载/cli-info/meta),没有独立列表方法。 - 双 API 面:
- 运营面(himarket-admin,5174,路径前缀
/api/v1/):admins/portals/developers/consumers/nacos/订阅——PATCH 不受支持(开发者审批走 8081 直连)。 - 市场面(himarket-server,8081,无前缀):products/skills/workers/mcp-servers/airegistries/gateways——管理端点
@AdminAuth。
- 运营面(himarket-admin,5174,路径前缀
- PublicAccess 端点:当前快照有 17 个
@PublicAccess注解,静态展开为 17 个 GET 端点(有效端点数以运行时扫描为准)。包括GET /products、/products/*/ref、/skills/*/cli-info、/skills/*/files、/workers/*/cli-info、/mcp-servers/meta/batch/public等。此前“34 个”的口径把注解注释/文档引用误计入,已回正。 - 开发者审批是硬环节:Portal
autoApproveDevelopers=false(需管理员审批),autoApproveSubscriptions=true(订阅自动批准)。
四、部署过程中的坑与解法(可复用)
| 坑 | 现象 | 解法 |
|---|---|---|
| jq 缺失 | install.sh 预检 Missing command: jq 退出 | 不可用假 jq 绕过。应安装经校验的 jq,或修改安装脚本显式跳过预检;本机临时绕过只能用于一次性实验并记录风险 |
| env 值带空格 | AI_MODEL_1_NAME=TokenPlan Qwen → Qwen: command not found | 值加引号 AI_MODEL_1_NAME="TokenPlan Qwen" |
| mysql 首次启动慢 | install.sh 报 mysql unhealthy 退出 | 首次初始化(建库+导 schema)耗时超重试窗口,实际已 healthy;docker compose up -d --no-recreate 续拉起 |
| init-nacos-db.sh CRLF | $'\r': command not found,nacos 库未建 | 修正脚本换行;手动补建仅限本地,需记录到复现脚本 |
| Nacos 数据库账号未授权 | nacos 连 MySQL Access denied | 创建独立 nacos 用户,仅授予 nacos 库所需权限;禁止使用 root@'%' + GRANT ALL |
| 5174 无市场面路由 | GET /api/v1/skills → 500 No static resource | 市场面走 8081 直连;5174 仅运营面代理 |
五、实证台账(本环境快照)
| 能力 | 状态 | 证据 |
|---|---|---|
| Nacos 实例登记 | ✅ | nacosId=nacos-ac8bc042783d4e379e066da332bfed71 |
| Skill 市场(Nacos 导入) | ✅ | AGENT_SKILL=174,skillConfig.nacosId 关联 |
| Worker 市场(Nacos 导入) | ✅ | WORKER=186,workerConfig.nacosId 关联 |
| 模型市场(MODEL_API 创建) | ✅ | TokenPlan Qwen Max,modelFeature 配置,total=1 |
| MCP 市场(产品+元数据+查询) | ✅ | mcp-7d648075c83842098f857eaba036aa5b,streamableHttp |
| Portal 创建 | ✅ | portal-78f54d2af4e142bfaa9c9d4cdb310969 |
| 开发者注册+审批 | ✅ | dev-47ec96c1983d4dc29ad4f2dcf5ec60a9 PENDING→APPROVED |
| 订阅链(模型+MCP) | ✅ | 2 条订阅均 APPROVED |
| 模型调用出口(Higress AI Provider/Route) | ⏳ 后置 | INSTALL_HIGRESS=false,装 Higress 后走 55-init 补 DNS 源/AI Provider/Route |
| MCP 端到端调用(tools 同步/refresh-tools) | ⏳ 后置 | 需真实 MCP Server(本机可起 sample MCP) |
| sandbox MCP 托管(deploy-sandbox) | ⏳ 后置 | 需 sandbox 部署配置 |
| OIDC 企业 SSO | ⏳ 后置 | Portal 挂 OIDC(02 篇) |
六、后置与建议
- Higress 网关出口:起 Higress+Redis,配置 DNS 服务源 → AI Provider → AI Route,并通过 Consumer 凭证完成一次真实调用与计量。
- MCP 端到端:起真实 streamable_http MCP Server,
refresh-tools拉工具清单 → 发布稳定端点 → 网关鉴权 → Broker 注入凭证 → 调用 → 审计。 - agent-skills 目录:himarket 仓库根有
.agent-skills/,可将企业 Skill 包直接推给POST /skills/{productId}/package上传,形成"自建 Skill 市场"。 - OIDC:Portal 设置挂
oidcConfigs,并先完成 ID Token 验签、iss/aud/nonce/state 校验;仅配置 Provider 不等于 SSO 安全可用。