使用 API 产品管理 MCP 工具访问权限

本页面适用于 Apigee,但不适用于 Apigee Hybrid

查看 Apigee Edge 文档。

本页介绍了如何使用 Apigee API 产品来控制对 MCP 工具的访问权限。无论您是使用 Apigee MCP 发现代理还是将流量代理到您自己的 MCP 服务器,都可以根据 API 产品配置对 MCP 客户端进行身份验证、应用每个工具的配额,以及过滤工具可见性。

MCP 服务器使用单个端点(例如 /mcp)来处理所有工具调用。与通过网址路径和 HTTP 方法区分操作的 REST API 不同,MCP 将操作嵌入到 JSON-RPC 请求正文中。Apigee 使用 ParsePayload 政策提取这些操作,以便按工具应用标准 API 管理政策(身份验证、配额强制执行和工具过滤)。

概览

如需使用 API 产品管理 MCP 工具访问权限,请完成以下步骤:

  1. 添加 ParsePayload 政策,以从请求正文中提取 MCP 工具名称。
  2. 使用 MCP 工具操作和每个工具的配额配置 API 产品
  3. 注册开发者应用以获取客户端凭据。
  4. 添加身份验证政策(API 密钥或 OAuth 2.0),以针对 API 产品验证客户端凭据。
  5. 添加配额政策以强制执行每个工具的速率限制。
  6. 测试工具过滤,以确认 tools/list 响应是否根据 API 产品配置进行过滤。

添加 ParsePayload 政策

ParsePayload 政策会解析 JSON-RPC 请求正文并提取 MCP 操作,例如 tools/call/get_weathertools/list。提取的操作存储在以政策名称(例如 parsepayload.ParsePayload-MCP.operation)为前缀的流变量中,下游政策会使用该变量进行身份验证和配额强制执行。

将以下 ParsePayload 政策添加到 MCP 代理的请求 PreFlow 中:

<ParsePayload name="ParsePayload-MCP">
    <DisplayName>Parse MCP Payload</DisplayName>
    <Source>request</Source>
    <PayloadType>JSON-RPC-2.0</PayloadType>
    <Protocol>MCP</Protocol>
</ParsePayload>

其中:

  • <Source>:要解析的消息。默认值为 request
  • <PayloadType>:载荷格式。必须为 JSON-RPC-2.0
  • <Protocol>:用于解析的协议。对于 MCP 服务器,必须为 MCP

执行后,该政策会填充以政策实例名称为前缀的流变量,遵循 parsepayload.policyName.suffix 模式。 对于名为 ParsePayload-MCP 的政策,系统会设置以下变量:

流变量 说明 示例值
parsepayload.ParsePayload-MCP.operation 用于 API 产品匹配和配额强制执行的派生操作名称。 tools/call/get_weather
parsepayload.ParsePayload-MCP.json-rpc.request.method 请求中的 JSON-RPC method 字段。 tools/call
parsepayload.ParsePayload-MCP.json-rpc.request.id 请求中的 JSON-RPC id 字段。 1
parsepayload.ParsePayload-MCP.json-rpc.request.params.name 请求中的 params.name 字段。 get_weather

配置包含 MCP 工具操作的 API 产品

API 产品用于定义客户端应用可以访问哪些 MCP 工具,以及每种工具的配额限制。您可以使用 API 产品定义中的 payloadOperationGroup 字段配置 MCP 工具操作。

payloadOperationGroup.operationConfigs 中的每个条目都指定了以下内容:

  • 用于提供 MCP 工具的 API 代理 (apiSource)。
  • 一项或多项工具操作(例如 tools/call/get_stock_pricetools/list)。
  • 相应操作集的可选配额。
API 产品创建界面,其中显示了“载荷操作”面板,其中 API 代理设置为 mcp-discovery,协议设置为 MCP,并显示了“列出”和“调用”的 MCP 操作类型选项以及配额配置。

使用以下 API 调用创建具有 MCP 工具操作的 API 产品:

curl -X POST \
  "https://apigee.googleapis.com/v1/organizations/ORG_NAME/apiproducts" \
  -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "PRODUCT_NAME",
    "displayName": "PRODUCT_DISPLAY_NAME",
    "approvalType": "auto",
    "payloadOperationGroup": {
      "operationConfigs": [
        {
          "apiSource": "MCP_PROXY_NAME",
          "operations": [
            { "operation": "tools/call/get_stock_price" },
            { "operation": "tools/call/get_company_news" }
          ],
          "quota": {
            "limit": "100",
            "interval": "1",
            "timeUnit": "minute"
          }
        },
        {
          "apiSource": "MCP_PROXY_NAME",
          "operations": [
            { "operation": "tools/list" }
          ],
          "quota": {
            "limit": "300",
            "interval": "1",
            "timeUnit": "minute"
          }
        }
      ]
    }
  }'

其中:

  • ORG_NAME 是您的 Apigee 组织的名称。
  • PRODUCT_NAME 是 API 产品的内部名称。
  • PRODUCT_DISPLAY_NAME 是 API 产品的显示名称。
  • MCP_PROXY_NAME 是将流量路由到 MCP 服务器的 API 代理的名称。这可以是 Apigee MCP 发现代理,也可以是使用您自己的 MCP 服务器作为后端的代理。

配置各个工具的配额

您可以为各个工具配置不同的配额。例如,以下配置将 get_stock_price 限制为每分钟 300 次调用,但将 get_company_news 限制为每分钟仅 3 次调用:

{
  "payloadOperationGroup": {
    "operationConfigs": [
      {
        "apiSource": "MCP_PROXY_NAME",
        "operations": [
          { "operation": "tools/call/get_stock_price" }
        ],
        "quota": { "limit": "300", "interval": "1", "timeUnit": "minute" }
      },
      {
        "apiSource": "MCP_PROXY_NAME",
        "operations": [
          { "operation": "tools/call/get_company_news" }
        ],
        "quota": { "limit": "3", "interval": "1", "timeUnit": "minute" }
      },
      {
        "apiSource": "MCP_PROXY_NAME",
        "operations": [
          { "operation": "tools/list" }
        ],
        "quota": { "limit": "300", "interval": "1", "timeUnit": "minute" }
      }
    ]
  }
}

您可以创建多个具有不同工具子集的 API 产品,以提供分层访问权限。 例如,基本产品可能仅包含 tools/call/get_stock_price,而高级产品包含所有可用工具,且配额更高。每个开发者应用都与一个或多个 API 产品相关联,因此不同的客户端会自动获得对不同工具集的访问权限,并具有独立的速率限制。

注册开发者应用

如需获取 API 密钥或 OAuth 凭据以进行测试,请注册开发者并创建与您在上一步中创建的 API 产品相关联的开发者应用。

  1. 在 Apigee 组织中注册应用开发者
  2. 创建开发者应用并将其与您的 API 产品相关联。
  3. 从应用凭据中获取使用方密钥 (API 密钥)。在后续的身份验证示例中使用此密钥。

添加身份验证政策

添加 ParsePayload 政策后,添加身份验证政策以验证客户端是否有权使用所请求的 MCP 工具。Apigee 会将提取的操作与客户端 API 产品中定义的操作进行匹配。

如果所请求的工具未列在客户端的 API 产品中,Apigee 会返回 401 Unauthorized 错误。

方法 1:API 密钥身份验证

使用 VerifyAPIKey 政策通过 API 密钥对客户端进行身份验证。将此政策添加到请求 PreFlow 中的 ParsePayload 政策之后:

<VerifyAPIKey name="VerifyAPIKey-1">
    <DisplayName>Verify API Key</DisplayName>
    <APIKey ref="request.queryparam.apikey"/>
</VerifyAPIKey>

客户端在调用 MCP 代理时,将 API 密钥作为查询参数传递:

curl -X POST "https://RUNTIME_HOSTNAME/mcp?apikey=API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/call",
    "params": { "name": "get_stock_price", "arguments": { "ticker": "GOOGL" } },
    "id": 1
  }'

您还可以将政策配置为从标头读取 API 密钥:

<VerifyAPIKey name="VerifyAPIKey-1">
    <DisplayName>Verify API Key</DisplayName>
    <APIKey ref="request.header.x-api-key"/>
</VerifyAPIKey>

方法 2:OAuth 2.0 身份验证

使用 OAuthV2 政策和 VerifyAccessToken 操作,通过 OAuth 2.0 访问令牌对客户端进行身份验证。将此政策添加到请求 PreFlow 中的 ParsePayload 政策之后:

<OAuthV2 name="OAuthV2-VerifyAccessToken">
    <DisplayName>Verify OAuth Access Token</DisplayName>
    <Operation>VerifyAccessToken</Operation>
</OAuthV2>

客户端在 Authorization 标头中传递访问令牌:

curl -X POST "https://RUNTIME_HOSTNAME/mcp" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/call",
    "params": { "name": "get_stock_price", "arguments": { "ticker": "GOOGL" } },
    "id": 1
  }'

如需详细了解如何在 Apigee 中配置 OAuth 2.0,请参阅 OAuth2 使用入门

添加配额政策

添加Quota政策,以强制执行 API 产品中定义的每个工具的速率限制。 该政策使用 UseQuotaConfigInAPIProduct 自动应用匹配的 API 产品操作中的配额配置。

在身份验证政策之后,将以下配额政策添加到请求 PreFlow:

<Quota name="Quota-PerToolLimit">
    <DisplayName>Per-Tool Quota</DisplayName>
    <UseQuotaConfigInAPIProduct stepName="AUTH_POLICY_STEP_NAME"/>
    <Distributed>true</Distributed>
</Quota>

其中,AUTH_POLICY_STEP_NAME 是身份验证政策 XML 元素中 name 属性的值(在本页的示例中为 VerifyAPIKey-1OAuthV2-VerifyAccessToken)。此值必须与政策的 name 属性(而非 <DisplayName>)匹配。

采用此配置后,每个工具操作都会根据 API 产品中定义的配额单独进行速率限制。例如,如果 tools/call/get_stock_price 的配额为每分钟 300 个,而 tools/call/get_company_news 的配额为每分钟 3 个,则即使这两个工具是通过同一代理访问的,每个限制也会单独实施。

完成代理配置

以下示例展示了 MCP 代理的完整请求 PreFlow 配置,其中包含 ParsePayload、API 密钥身份验证和按工具配额强制执行:

<ProxyEndpoint name="default">
    <PreFlow>
        <Request>
            <Step>
                <Name>ParsePayload-MCP</Name>
            </Step>
            <Step>
                <Name>VerifyAPIKey-1</Name>
            </Step>
            <Step>
                <Name>Quota-PerToolLimit</Name>
            </Step>
        </Request>
    </PreFlow>
    <HTTPProxyConnection>
        <BasePath>/mcp</BasePath>
    </HTTPProxyConnection>
    <RouteRule name="default">
        <TargetEndpoint>default</TargetEndpoint>
    </RouteRule>
</ProxyEndpoint>

工具过滤

当客户端通过 MCP 代理发送包含 API 密钥或 OAuth 身份验证的 tools/list 请求时,Apigee 会自动过滤响应,使其仅包含在客户端的 API 产品中注册的工具。

例如,如果客户端的 API 产品包含 tools/call/get_stock_pricetools/call/get_company_news 操作,则来自 MCP 服务器的 tools/list 响应将被过滤,仅返回 get_stock_priceget_company_news,即使 MCP 服务器公开了其他工具也是如此。

如果存在以下配置,系统默认会进行此过滤。无需专用过滤政策:

  • 请求 PreFlow 包含 ParsePayload 和身份验证政策(VerifyAPIKey 或 OAuthV2)。
  • API 产品在 payloadOperationGroup 中包含 tools/list
  • API 产品用于指定客户端可以访问的工具操作(例如 tools/call/get_stock_price)。

如需测试工具过滤,请发送包含客户端 API 密钥的 tools/list 请求:

curl -X POST "https://RUNTIME_HOSTNAME/mcp?apikey=API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/list",
    "id": 1
  }'

如果 API 产品包含 tools/call/get_stock_pricetools/call/get_company_news,则过滤后的响应类似于以下内容,即使 MCP 服务器公开了其他工具也是如此:

{
  "jsonrpc": "2.0",
  "result": {
    "tools": [
      {
        "name": "get_stock_price",
        "description": "Get the current stock price for a given ticker symbol.",
        "inputSchema": {
          "type": "object",
          "properties": {
            "ticker": { "type": "string", "description": "Stock ticker symbol" }
          },
          "required": ["ticker"]
        }
      },
      {
        "name": "get_company_news",
        "description": "Get recent news articles for a company.",
        "inputSchema": {
          "type": "object",
          "properties": {
            "company": { "type": "string", "description": "Company name" }
          },
          "required": ["company"]
        }
      }
    ]
  },
  "id": 1
}

未在 API 产品中列出的工具(例如 delete_accountadmin_reset)会自动从响应中移除。

以下调试会话显示了响应流程中的 McpToolsFilterExecution 步骤,其中 mcp_flow_info.mcp.allowed.tools 属性列出了 API 产品允许的工具:

调试会话,显示了 McpToolsFilterExecution 步骤,其中 mcp_flow_info.mcp.allowed.tools 列出了过滤后的工具。

使用条件流实现每个工具的逻辑

当您需要的工具级逻辑超出 API 产品配额提供的范围时,请使用条件流,例如应用特定于工具的 SpikeArrest 速率、路由到不同的后端或为特定工具添加请求转换。条件流使用 parsepayload.policyName.operation 流变量来匹配提取的 MCP 操作。

对于名为 ParsePayload-MCP 的 ParsePayload 政策:

<Flows>
    <Flow name="ListTools">
        <Condition>(parsepayload.ParsePayload-MCP.operation = "tools/list")</Condition>
        <Request/>
    </Flow>
    <Flow name="GetStockPrice">
        <Condition>(parsepayload.ParsePayload-MCP.operation = "tools/call/get_stock_price")</Condition>
        <Request>
            <Step>
                <Name>SpikeArrest-StockPrice</Name>
            </Step>
        </Request>
    </Flow>
    <Flow name="GetCompanyNews">
        <Condition>(parsepayload.ParsePayload-MCP.operation = "tools/call/get_company_news")</Condition>
        <Request>
            <Step>
                <Name>SpikeArrest-CompanyNews</Name>
            </Step>
        </Request>
    </Flow>
</Flows>

调试代理配置

使用 Apigee Debug 工具验证 ParsePayload 政策是否正确提取了 MCP 操作,以及身份验证和配额政策是否按预期运行。

调试会话,显示了 ParsePayload-MCP 步骤,其中包含设置为 tools/list 的流变量 parsepayload.ParsePayload-MCP.operation。

在调试会话中,检查 ParsePayload 政策步骤(其中 ParsePayload-MCP 是政策名称)之后的以下流变量:

  • parsepayload.ParsePayload-MCP.operation:应包含完整的操作名称(例如 tools/call/get_stock_price)。
  • parsepayload.ParsePayload-MCP.json-rpc.request.method:应包含 JSON-RPC 方法(例如 tools/call)。

限制

  • ParsePayload 政策仅支持 JSON-RPC-2.0 作为载荷类型。
  • API 产品工具操作仅支持 tools/calltools/list 方法。针对 tools/list 响应的工具过滤仅适用于 API 产品中配置的 tools/call 操作。
  • ParsePayload 政策会解析整个请求正文。Apigee 强制执行 10 MB 的默认请求正文大小限制,您可以使用 request.payload.parse.limit 属性将此限制配置为最高 30 MB。如需了解详情,请参阅端点属性参考文档
  • 采用 MCP 协议的 ParsePayload 政策仅解析 JSON-RPC 请求载荷(包含 methodparams 字段)。MCP 响应载荷未被解析。
  • tools/list 回答进行工具过滤需要在请求 PreFlow 中添加 ParsePayload 和身份验证政策。

后续步骤