wso2~关于workbuddy中mcp在wso2中的授权端点


{
  "resource": "https://test-apim-gateway.xxx.com/test/1.0.0/mcp",
  "authorization_servers": [
    "https://kc.com/auth/realms/xx/protocol/openid-connect/token"
  ],
  "scopes_supported": [
    "openid",
    "wso2-role"

  ]
}

  • 在apimgt.org.wso2.carbon.apimgt.gateway项目中做了相关适配合

在admin平台添加自定义的key manager ,状态为关闭,避免对其它api产生影响

设置kc相关的idp配置,状态为关闭,否则会影响默认的key manager

这样,在访问这个mcp端点时,authorization_servers就变成了kc的地址,而不是wso2默认的key manager的地址。

查看是否安装成功,如果没有生效,执行下面代码也可能让它生效,有时是缓存问题

C:\Users\User>curl -k -s "https://apim.xxx.com/api/am/publisher/v4/swagger.yaml" | grep -A 25 "refresh-tools"
  /mcp-servers/{mcpServerId}/refresh-tools:
    post:
      tags:
      - MCP Servers
      summary: Refresh MCP tools from the backend
      description: |
        Re-synchronizes tool definitions from the upstream MCP endpoint for MCP servers of subtype **SERVER_PROXY**,
        or reapplies MCP tool mappings from the current stored OpenAPI / backend definition for other MCP server subtypes.
        The MCP server metadata is persisted the same way as a regular update, and matching per-tool policies and
        scopes are preserved when tool names are unchanged (proxy subtype).
      operationId: refreshMCPServerTools
      parameters:
      - $ref: "#/components/parameters/mcpServerId"
      responses:
        "200":
          description: |
            OK.
            MCP server tools refreshed; response body is the updated MCP server.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/MCPServer"
        "400":
          $ref: "#/components/responses/BadRequest"
        "403":
          $ref: "#/components/responses/Forbidden"
--
          \ \"https://127.0.0.1:9443/api/am/publisher/v4/mcp-servers/7a2298c4-c905-403f-8fac-38c73301631f/refresh-tools\""
  /mcp-servers/{mcpServerId}/comments:
    get:
      tags:
      - Comments
      summary: Retrieve MCP Server Comments
      description: |
        Get a list of Comments that are already added to MCP Server
      operationId: getAllCommentsOfMCPServer
      parameters:
      - $ref: "#/components/parameters/mcpServerId"
      - $ref: "#/components/parameters/requestedTenant"
      - $ref: "#/components/parameters/limit"
      - $ref: "#/components/parameters/offset"
      - $ref: "#/components/parameters/includeCommenterInfo"
      responses:
        "200":
          description: |
            OK.
            Comments list is returned.
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CommentList"
        "404":
          $ref: "#/components/responses/NotFound"



workbuddy认证流程

sequenceDiagram participant UI as 连接器面板 participant WB as WorkBuddy 主进程 participant Store as .credentials.json participant IdP as 企查查 OAuth participant MCP as MCP 服务 UI->>WB: 点击连接 qcc-company WB->>IdP: 发现元数据 + 注册/加载 client_id WB->>Store: saveClientInfo (mcpClientInfo) WB->>UI: 打开浏览器授权页 IdP->>WB: 回调 workbuddy://…/oauth/callback?code= WB->>IdP: code 换 access_token + refresh_token WB->>Store: saveTokens (mcpOAuth) WB->>MCP: 带 Bearer 调用 tools/list、tools/call

流程

flowchart LR WB[WorkBuddy 客户端] GW[apim-gateway.xxx.com<br/>WSO2 APIM 资源服务器] KC[testcas.xxx.com<br/>Keycloak 授权服务器] WB –>|POST /mcp-law-agg/1.0.0/mcp| GW GW –>|401 + WWW-Authenticate| WB WB –>|读 oauth-protected-resource| GW WB –>|授权页 / 换 token| KC GW –>|校验 Bearer| GW

流程

sequenceDiagram participant WB as WorkBuddy participant GW as APIM 网关 participant IdP as 授权服务器 WB->>GW: POST /mcp (initialize 或 tools/list,无 Token) GW–>>WB: 401 + WWW-Authenticate WB->>WB: auth() 发现 OAuth 元数据 WB->>IdP: 打开浏览器授权页 Note over WB: 用户登录并同意 IdP–>>WB: workbuddy://…/oauth/callback?code= WB->>IdP: 用 code 换 access_token WB->>GW: 带 Bearer 重试 MCP 请求

流程

sequenceDiagram participant WB as WorkBuddy participant Meta as APIM 元数据 participant KC as Keycloak participant GW as APIM Gateway WB->>Meta: GET oauth-protected-resource Meta–>>WB: authorization_servers = Keycloak realm WB->>KC: OAuth 登录 + 换票 KC–>>WB: KC JWT WB->>GW: MCP + Bearer KC JWT Note over GW: 网关校验 KC JWT 或自动换 WSO2 token GW–>>WB: 200 / tools

workbuddy连接器流程

flowchart LR
  A[连接器 UI 显示法律聚合] --> B[用户 mcp.json 有条目]
  C[点击连接] --> D[查找 connectors/mcp-law-agg/mcp.json]
  D --> E[文件不存在 → 报错]

本地部署一下拦截器

文件 作用
connectors-marketplace/connectors/test/mcp.json MCP 端点配置(连接时读取)
connectors-marketplace/connectors/test/connector-meta.json 名称、描述、示例
connectors-marketplace/connectors/test/skills/SKILL.md 连接成功后的 Skill
connectors-marketplace/connectors/test/icon.svg 连接器图标
connectors-marketplace/icons/test.svg 市场列表图标
connectors-marketplace/.codebuddy-connector/connectors.json 已登记 test(含 type: "mcp"

MCP 地址:

https://test-apim-gateway.xxx.com/mcp-law-agg/1.0.0/mcp

keycloak开始PKCE

Keycloak 要求「客户端必须启用 PKCE」——在服务端配置
WorkBuddy 不能在连接器配置里给 DCR 增加自定义字段(当前版本没有该入口)。应在 Keycloak 侧处理:

方案 A:Realm / Client Policy 强制 PKCE(推荐)

  • Realm → Client policies → Policies
  • 添加 PKCE Enforcer(pkce-enforcer)
  • 对 public 客户端或 DCR 创建的客户端生效
  • 这样即使用 DCR 注册的客户端未勾选 PKCE,每次授权仍强制带 code_challenge,与 WorkBuddy 行为一致。

注意:WorkBuddy 每次点「连接」会清本地 client_id 再 DCR;要稳定用预建 client,需要产品支持静态 client_id,或接受 DCR 后由脚本批量改客户端属性。

方案 C:DCR 之后用 Admin API 补属性
对 DCR 生成的 client_id 调用 Admin REST API,设置:

"attributes": {
  "pkce.code.challenge.method": "S256"
}

或在 UI:Clients → 该客户端 → Advanced → PKCE Code Challenge Method = S256。

这是 注册之后 的配置,不是让 WorkBuddy 在 DCR 里传 PKCE。

问题

能否统一用一个 Keycloak 客户端?
Keycloak 侧可以预建一个固定客户端,但 WorkBuddy 目前没有官方配置项指定「法律聚合」用固定 client_id。

预建客户端需要至少:

  • Client ID:固定 UUID(由你们在 KC 创建)
  • Redirect URI(必须完全一致):
    workbuddy://workbuddy/mcp/connector%3Amcp-law-agg/oauth/callback
  • Access Type:public(WorkBuddy 使用 PKCE,token_endpoint_auth_method: none)
  • Standard Flow:开启
  • PKCE:S256
    但仅预建还不够:WorkBuddy 每次点连接仍会 deleteClientInfo,然后再次 DCR,KC 里还是会不断增加动态客户端。

手动写入 .credentials.json 的 mcpClientInfo 也会被下一次点「连接」清掉,无法稳定复用。

可行建议

  1. 运维侧(Keycloak)
    预建一个客户端,例如 workbuddy-mcp-law-agg(名称自定)
    在 realm 限制或关闭面向公网的 DCR(Initial Access Token、注册策略等),避免匿名无限注册
    定期清理 WorkBuddy Connector (connector:mcp-law-agg) 这类动态客户端

  2. 联调侧(减少重复点连接)
    先修好 oauth-protected-resource 和 token 类型问题,争取 一次授权成功。成功后 WorkBuddy 会保存 token,一般不必反复点「连接」,KC 客户端增长会明显变慢。

  3. 产品侧(根本方案)

向 WorkBuddy 提需求,例如:

连接器支持配置 静态 client_id / client_secret
或:用户已授权时,点「连接」不要清除 client 作用域的凭证
在 WorkBuddy 改之前,无法在客户端配置里做到「统一只用一个 KC 客户端且稳定复用」。

结论:可以、也应当在 Keycloak 统一预建一个客户端;但按当前 WorkBuddy 逻辑,每次点「连接」仍会触发新的 DCR。要真正复用固定 client,需要 WorkBuddy 支持静态 client,或 connect 时不再清除已保存的 client_id。

如果你需要,我可以写一段给 Keycloak 管理员的「预建客户端 + 限制 DCR」检查清单(含 redirect URI 和 PKCE 配置项)。

难点

  • 目前mcp通过wso2系统进行权限控制
  • 用户体系依赖于kc
  • workbuddy对接kc后,生成的是kc的token
  • kc的token无法直接对mcp进行资源访问
  • ?需要在code to token环节,将kc的token置换为wso2的token,再为用户生成一个应用的token,这样才能应用到订阅的mcp服务上面
  • ?DCR注册客户端后,如何让PKCE生效,目前通过监听client_register进行添加pkce,是有延时的,这是workbuddy会出现pkce的错误
  • ?平

对接到kc后如何置换wso2应用token

涉及的平台

  • wso2平台,用来做mcp服务的管理和mcp的资源认证
  • keycloak平台,是一个idp认证平台,用来做用户认证,并与wso2平台进行token的交互
  • workDubby工具,它是一个C端工具,用来调用mcp服务

具体流程

  • wos2-mcp服务添加.well-known/oauth-protected-resource端点
  • 访问mcp资源返回401时,同时输出响应头www-authenticate
    Bearer resource_metadata=”https://test-apim-gateway.xxx.com/weather/1.0/.well-known/oauth-protected-resource“, error=”invalid_token”, error_description=”Access token is missing or invalid”
  • 从resource_metadata端点获取authorization_servers,进行认证
  • 跳到authorization_server所对应的idp进行认证
  • 通过DCR(动态客户端注册)向IDP添加一个客户端
  • 在IDP中添加wos2的IDP,用来与wso2通讯
  • 注册客户端后,向idp发起登录请求,登录成功后返回code
  • 通过code获取token,同时修改idp源码
    • 访问wso2认证接口,进行token的交换
    • 拿到wso2接口访问用户的应用,没有应用需要新建
    • 拿到默认应用后,获取它的consumerkey,没有就新建
    • 通过consumerkey和应用ID获取应用的token
    • 使用应用token覆盖kc生成的token,并返回给workbuddy
    • ?判断应用是否订阅了当前mcp
    • ?如果没有订阅,需要先为它进行mcp的订阅
  • 通过token访问mcp资源

文章摘自:https://www.cnblogs.com/lori/p/20279750