push-inventory-collector

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Push inventory collector

推送清单采集器

Generate one collector script for one self-managed scanner configuration. Do not assume a cloud vendor, a programming language, or a credential shape until the customer provides them. The script is the pull-scanner connection form on their machine, in the language they name. It reads their APIs, builds one payload per asset, uploads each payload, and then commits the scan. The scanner reconciles and publishes. The script does not publish by itself.
There is no universal provider credential set. There is no schedule on this scanner. Do not add a schedule, a last-run time, or a "run discovery" step.
为一个自托管 scanner 配置生成一个采集脚本。在客户提供信息前,不要假定云厂商、编程语言或凭据结构。脚本应采用客户指定的语言,作为其机器上的 pull-scanner 连接表单。它读取客户的 API,为每个资产生成一个 payload,上传每个 payload,然后提交扫描。由 scanner 执行核对和发布;脚本本身不负责发布。
不存在通用的 provider 凭据集合。此 scanner 也没有调度机制。不要添加调度、上次运行时间或“运行发现”步骤。

When to Use This Skill

何时使用此 Skill

Use this skill when the user asks to:
  • Generate a collector script for a self-managed scanner
  • How to Push, download the collector skill, or push inventory
  • Write a script that calls POST /push then POST /commit
Trigger keywords: push inventory, push script, How to Push, self-managed scanner, collector skill, POST /push, POST /commit.
Do NOT use this skill when: creating a pull scanner that discovers from a connected cloud platform — use skill setup-service-scanner. Running a hosted scan and reviewing staging assets — use skill run-service-scan-and-view-results.
当用户要求以下事项时使用此 Skill:
  • 为自托管 scanner 生成采集脚本
  • How to Push、下载 collector skill,或推送 inventory
  • 编写先调用 POST /push、再调用 POST /commit 的脚本
触发关键词: push inventory、push script、How to Push、self-managed scanner、collector skill、POST /push、POST /commit。
不要在以下场景使用此 Skill: 创建用于从已连接云平台发现资产的 pull scanner——请使用 skill setup-service-scanner;运行托管扫描并检查暂存资产——请使用 skill run-service-scan-and-view-results。

Prerequisites

前置条件

  • Organization id and scanner configuration id copied from the self-managed scanner page
  • A Connected App with client-credentials grant and
    manage:exchange
    on that organization
  • The provider API specification they can paste or attach (OpenAPI, Postman, or a redacted request and response)
  • Authentication documentation for those APIs, without secret values
  • A language they can run on their machine
  • 从自托管 scanner 页面复制的 Organization id 和 scanner configuration id
  • 一个使用 client-credentials grant、并且在该组织上拥有
    manage:exchange
    权限的 Connected App
  • 客户可粘贴或附加的 provider API 规范(OpenAPI、Postman,或已脱敏的请求与响应)
  • 这些 API 的认证文档,但不得包含 secret 值
  • 客户机器上能够运行的编程语言

Reference files

参考文件

  • references/scanner-contract.md
    — ZIP layout, POST /push multipart, POST /commit body. Read it before writing the upload and commit functions.
  • references/generated-script-standard.md
    — runtime inputs, stderr stages, JSON stdout, mapping fingerprint. Read it when writing the script.
  • references/provider-auth-resolution.md
    — one question per turn, managed-only auth, new-provider contract. Read it when choosing operations and credential fields.
  • references/scanner-contract.md
    ——ZIP 布局、POST /push multipart、POST /commit 请求体。编写上传和提交函数前必须阅读。
  • references/generated-script-standard.md
    ——运行时输入、stderr 阶段、JSON stdout、mapping fingerprint。编写脚本时必须阅读。
  • references/provider-auth-resolution.md
    ——每轮只问一个问题、仅托管端可执行的认证方式、新 provider 契约。选择操作和凭据字段时必须阅读。

Workflow

工作流

Rules that always apply

始终适用的规则

  1. Customer-facing words — use the table below in every question, in
    --help
    , in the FAILED block, and in Ways to run the script. A wrong verb here is a generation failure.
  2. One question per response — never combine asset type, inventory, auth, or language.
  3. Never ask for a provider name — infer the provider from a usable spec. On an unreadable or incomplete spec, ask only the missing list, fetch, handshake, export, or auth piece.
  4. Never reorder — skip a step only when this chat already answered it with usable data. Ask a step again when the previous answer was unreadable, the wrong kind of file, or missing a required piece.
  5. Do not create a scanner during generation — do not log in, do not call Anypoint CLI, do not mint a token to discover an organization. Organization id and configuration id are values copied from the scanner page into the inputs file or the parameters.
Use these words. Do not hard-code a vendor, a non-production host, or a loopback address into a question or an example host. The example host is
https://anypoint.mulesoft.com
.
SayDo not say
scriptadapter, collector, product command
input file, parameters, or promptsthree CLIs, CLI mode
self-managed scannerself-serve, self-service, build your own
commit the scanseal, seal the zip, complete and publish, publish to Exchange
The upload call is
POST .../push
. The finish call is
POST .../commit
. The question is exactly: "Commit this scan? [y/N]". A generated script that calls
POST .../seal
,
POST .../complete
, or
POST .../push-assets
is a generation failure. The JSON body still has a boolean field named
complete
. That field is not the customer sentence.
Examples of an inventory (OpenAPI, a Postman collection, a redacted request and response) show the shape. They are not a menu and not a default. Language examples are not a fixed list. Do not default to one language.
A script that creates a configuration, calls
anypoint-cli
, or calls
GET /accounts/api/me
in order to invent an organization id is a generation failure. That auto-fill is later work. It is not this script.
The only customer questions in this chat are the quoted sentences in Steps 1–5, the missing-piece follow-ups, "Does this look fine?", and the generated script's "Commit this scan? [y/N]". Do not ask which provider.
  1. 面向客户的措辞——在每个问题、
    --help
    、FAILED 块和脚本运行方式中使用下表。这里使用错误动词即视为生成失败。
  2. 每次响应只问一个问题——绝不能把资产类型、清单、认证或语言合并询问。
  3. 绝不询问 provider 名称——从可用的规范中推断 provider。如果规范无法读取或不完整,只询问缺少的列表、获取、握手、导出或认证部分。
  4. 绝不调整顺序——只有当前对话已经提供了可用数据时,才能跳过某一步。如果之前的回答无法读取、文件类型错误或缺少必要内容,则必须重新询问该步骤。
  5. 生成期间不要创建 scanner——不要登录,不要调用 Anypoint CLI,也不要签发 token 来发现 organization。Organization id 和 configuration id 应从 scanner 页面复制到输入文件或参数中。
请使用以下词语。不要在问题或示例 host 中硬编码厂商、非生产环境 host 或 loopback 地址。示例 host 为
https://anypoint.mulesoft.com
。
使用不要使用
scriptadapter, collector, product command
input file, parameters, or promptsthree CLIs, CLI mode
self-managed scannerself-serve, self-service, build your own
commit the scanseal, seal the zip, complete and publish, publish to Exchange
上传调用为
POST .../push
,结束调用为
POST .../commit
。问题必须逐字为:
"Commit this scan? [y/N]"
。生成调用
POST .../seal
、
POST .../complete
或
POST .../push-assets
的脚本即视为生成失败。JSON 请求体仍有一个名为
complete
的 boolean 字段,但该字段不是面向客户的问题。
Inventory 示例(OpenAPI、Postman collection、已脱敏的请求与响应)仅用于展示结构,并不是选项菜单或默认值。语言示例也不是固定列表。不要默认使用某一种语言。
创建配置、调用
anypoint-cli
,或为了自行推断 organization id 而调用
GET /accounts/api/me
的脚本均视为生成失败。这种自动填充属于后续工作,不属于本脚本。
本对话中唯一允许面向客户提出的问题,是步骤 1–5 中加引号的句子、缺失信息的追问、
"Does this look fine?"
,以及生成脚本中的
"Commit this scan? [y/N]"
。不要询问 provider 名称。

Step 1: Ask asset type

步骤 1:询问资产类型

When the asset type is not already explicit, the whole message is:
"What asset type does this scanner configuration accept? Reply with one of: agent, mcp, or rest-api.
agent is one agent card. mcp is one MCP server card. rest-api is one API description. One script commits one of these, to one configuration."
Then stop.
Explicit means they wrote
agent
,
mcp
, or
rest-api
, or a harmless alias (
agents
→
agent
,
api
/
REST APIs
/
APIs
→
rest-api
,
MCP
/
MCP servers
→
mcp
). A provider name, a file name, or an operation name is not an asset type. Do not infer the asset type from a single-type contract. Inferring the type so generation can jump ahead is a generation failure.
如果尚未明确资产类型,整条消息必须为:
`"What asset type does this scanner configuration accept? Reply with one of: agent, mcp, or rest-api.
agent is one agent card. mcp is one MCP server card. rest-api is one API description. One script commits one of these, to one configuration."`
然后停止。
明确意味着用户写入了
agent
、
mcp
或
rest-api
,或者写入了无害别名(
agents
→
agent
,
api
/
REST APIs
/
APIs
→
rest-api
,
MCP
/
MCP servers
→
mcp
)。Provider 名称、文件名或 operation 名称不属于资产类型。不要根据单类型契约推断资产类型。为了直接进入生成阶段而推断类型即视为生成失败。

Step 2: Collect inventory

步骤 2:收集清单

Once the type is known, the whole next message is:
"Please provide the API specification or documentation for the provider APIs that list and fetch these assets. OpenAPI or Swagger, a Postman or Insomnia collection, RAML, an API Blueprint, a GraphQL schema, an SDK reference, or a redacted request and response are examples, not required formats."
Then stop. Do not ask which provider. Infer the provider from a usable spec. Do not invent calls. Do not fetch a spec they did not provide. The catalog later in this file is a shape reminder for a matching paste, not a substitute.
Read what they attached. Then stop if it is not yet usable. Ask only the missing piece. One question per response.
  • Unreadable, empty, unrelated, or not a spec or redacted request and response. Whole message: "This attachment is not a usable specification for listing and fetching these assets. Please attach or paste a valid API spec or a redacted request and response that includes those APIs."
  • No list API for the type they named. Whole message: "This specification does not include an API that lists {agent|mcp|rest-api} assets. Please attach or paste that list API."
  • Agent list with no fetch or card API. Whole message: "This specification lists assets but does not include the fetch or card API needed to build the agent zip. Please attach or paste that call."
  • MCP list with no
    initialize
    /
    tools/list
    (or the equivalent handshake). Whole message: "This specification does not include initialize and tools/list (or the equivalent handshake) needed to build an MCP card. Please attach or paste those calls."
  • REST list with no export or OpenAPI download. Whole message: "This specification does not include the export or OpenAPI download needed to build a REST zip. Please attach or paste that call."
A usable inventory has the list call plus the fetch, card, handshake, or export that type needs. Only then ask authentication. Vertex MCP, Gemini MCP, Gemini agents, Azure AI Foundry MCP, and Microsoft 365 Copilot with no customer list docs are enum-only: ask for a customer list call, or stop. If they ask which file to use, they only have this skill and the files they attach; do not name a path from this package.
类型明确后,下一条消息必须完整写为:
"Please provide the API specification or documentation for the provider APIs that list and fetch these assets. OpenAPI or Swagger, a Postman or Insomnia collection, RAML, an API Blueprint, a GraphQL schema, an SDK reference, or a redacted request and response are examples, not required formats."
然后停止。不要询问 provider 名称。要从可用规范中推断 provider。不要自行创造调用。不要获取用户未提供的规范。本文件中后续的 catalog 只是用于匹配粘贴内容的结构提示,不能替代用户提供的规范。
阅读用户附加的内容。如果尚不可用,则停止并只询问缺失部分。每次响应只问一个问题。
  • 内容无法读取、为空、不相关,或者既不是规范也不是已脱敏的请求与响应。整条消息必须为:
    "This attachment is not a usable specification for listing and fetching these assets. Please attach or paste a valid API spec or a redacted request and response that includes those APIs."
  • 用户指定类型的清单中没有 list API。整条消息必须为:
    "This specification does not include an API that lists {agent|mcp|rest-api} assets. Please attach or paste that list API."
  • Agent 清单中没有 fetch 或 card API。整条消息必须为:
    "This specification lists assets but does not include the fetch or card API needed to build the agent zip. Please attach or paste that call."
  • MCP 清单中没有
    initialize
    /
    tools/list
    或等效握手。整条消息必须为:
    "This specification does not include initialize and tools/list (or the equivalent handshake) needed to build an MCP card. Please attach or paste those calls."
  • REST 清单中没有 export 或 OpenAPI download。整条消息必须为:
    "This specification does not include the export or OpenAPI download needed to build a REST zip. Please attach or paste that call."
可用清单必须包含 list 调用,以及该资产类型所需的 fetch、card、握手或 export。只有满足这些条件后,才能询问认证方式。Vertex MCP、Gemini MCP、Gemini agents、Azure AI Foundry MCP 和 Microsoft 365 Copilot 如果没有客户自己的 list 文档,则属于仅枚举支持:要求客户提供 list 调用,或者停止。如果用户询问应使用哪个文件,说明其只有当前 Skill 和自己附加的文件;不要指出本软件包中的路径。

Step 3: Collect authentication

步骤 3:收集认证信息

Once the inventory is usable, the whole next message is:
"Please provide the authentication documentation needed to call those APIs. Include the token or signing request, the response, which field is a secret, and how a call is proven to be the right account. Do not paste secret values."
Then stop. A long-lived secret, a session token, and a private key are never typed into this chat. They belong in the inputs file or in the environment when the script runs.
If that document is missing a piece, ask only that piece. Whole message, fill one gap: "The authentication documentation is missing {the token or signing request|the response|which field is a secret|how a call is proven to be the right account}. Please add that piece. Do not paste secret values." Do not proceed to language until those four are present.
Use the authentication document they pasted. Do not open a catalog file from this skill. When they describe Salesforce connected-org (C2C) login or a MuleSoft-managed authorization-code flow, that is not customer-executable: ask for a request and response they can run from their machine. Until they provide one, do not write files. A pasted SigV4 access-key flow still uses the request and response they pasted. Do not copy pull-scanner-only fields such as Hub Role ARN, Spoke Role Name, External ID, Account IDs, or Target Regions into the script.
清单可用后,下一条消息必须完整写为:
"Please provide the authentication documentation needed to call those APIs. Include the token or signing request, the response, which field is a secret, and how a call is proven to be the right account. Do not paste secret values."
然后停止。长期有效的 secret、session token 和 private key 绝不能输入到对话中。它们应放在输入文件里,或者在脚本运行时通过环境变量提供。
如果认证文档缺少某一部分,只询问该部分。整条消息必须为:
"The authentication documentation is missing {the token or signing request|the response|which field is a secret|how a call is proven to be the right account}. Please add that piece. Do not paste secret values."
在这四项全部具备前,不要进入语言选择步骤。
使用用户粘贴的认证文档。不要打开此 Skill 中的 catalog 文件。当用户描述 Salesforce connected-org(C2C)登录或 MuleSoft 托管的 authorization-code 流程时,这种方式无法由客户直接执行:要求客户提供可从其机器运行的请求和响应。在用户提供之前,不要编写文件。粘贴的 SigV4 access-key 流程仍需使用用户提供的请求和响应。不要把 Hub Role ARN、Spoke Role Name、External ID、Account IDs 或 Target Regions 等仅供 pull scanner 使用的字段复制到脚本中。

Step 4: Ask script language

步骤 4:询问脚本语言

Once auth is known, the whole next message is:
"Which script language should I use? Project conventions are optional. Any language you can run is acceptable. Named languages are examples, not a fixed list."
Then stop. Do not default to a language. Writing a file before they answer is a failure. If they name a language and omit conventions, write a plain script in that language.
Default script stderr the customer sees: the numbered step banner only when that step runs; after a successful list
listed N, matching M, skipped K
; then one line per matching asset (
type
, external id, display name);
No matching {ASSET_TYPE} assets found.
when M is 0; FAILED for real failures. Do not print skip ids,
skipping MCP
, or
not MCP
unless
--verbose
.
认证方式明确后,下一条消息必须完整写为:
"Which script language should I use? Project conventions are optional. Any language you can run is acceptable. Named languages are examples, not a fixed list."
然后停止。不要默认使用某种语言。在用户回答前写文件即视为失败。如果用户指定语言但没有说明项目约定,则使用该语言编写普通脚本。
客户看到的默认 stderr:仅在对应步骤实际执行时打印编号步骤横幅;成功 list 后打印
listed N, matching M, skipped K
;随后每个匹配资产打印一行(
type
、external id、display name);当 M 为 0 时打印
No matching {ASSET_TYPE} assets found.
;真实失败时打印 FAILED。除非使用
--verbose
,不要打印被跳过的 id、
skipping MCP
或
not MCP
。

Step 5: Show the mapping

步骤 5:展示映射

[GATE] WAIT for an explicit yes to "Does this look fine?" before writing files.
When type, inventory, auth, and language are known, do not write files in that turn. Show the mapping in this order, then stop. Do not treat dumping the script as having shown the mapping.
  1. What was collected, in plain English: the list and detail calls, the auth field names (not values), the language, and the one asset type.
  2. One row per inventory call. Columns: Call, Request, Response field, Zip path.
  3. One row per field the zip will contain. Columns: Source, Sent as, Required. Source is the operation and response path, or
    constant
    . If a required Source cannot be pointed at, leave the row blank and ask only for that API or field. Do not guess. If any required Source is blank, stop here. Do not show items 4–8 and do not ask "Does this look fine?" until every required Source is filled.
  4. One Representative generated JSON object for a single asset, using values from their inventory when they gave an example, otherwise empty strings. For
    agent
    , every required A2A v0.3 field has a row (
    name
    ,
    description
    ,
    protocolVersion
    ,
    url
    ,
    version
    ,
    capabilities
    ,
    defaultInputModes
    ,
    defaultOutputModes
    ,
    skills
    ). A v1 card uses
    supportedInterfaces
    or
    supported_interfaces
    and has no top-level
    url
    . The artifact is
    a2a-card.json
    or
    a2a-v1-card.json
    . For
    mcp
    ,
    specification/mcp-metadata.json
    with
    transport
    required; if capabilities are included, include all four booleans
    tools
    ,
    resources
    ,
    prompts
    , and
    logging
    ; do not add
    serverInfo
    . For
    rest-api
    ,
    specification/oas.json
    with
    info
    and
    paths
    ;
    externalId
    is the provider id, and one stage is one asset.
  5. How the zip is uploaded after they run the script:
    POST {ANYPOINT_BASE}/agent-scanner/api/v1/organizations/{org}/scanner-configurations/{config}/push
    is the zip as multipart part
    file
    , filename
    {externalId}.zip
    . Not JSON. Finish is a separate
    POST .../commit
    . The customer question is "Commit this scan? [y/N]". Do not name
    /push-assets
    ,
    /complete
    , or
    /seal
    .
  6. Script architecture: the function names to write (provider login, list, shape zip, token, upload, optional commit, print status) and the numbered stderr steps below.
  7. Flags, environment variables, prompts, and which of those are secret. Same names as The script.
    --help
    three columns: Prompt label, Parameter flag, Input file key.
  8. Ask exactly: "Does this look fine?"
Do not show Prerequisites or Ways to run the script in this turn. Those come after the files exist. Showing them before they say yes is a generation failure.
If they say no, ask which row is wrong, fix the table, and ask again. Still do not write files. If they say yes, write the two files. After the files exist, show Prerequisites, then Ways to run the script in this order: interactive, parameters, input file, and the full
inputs.env
as a fenced block named
inputs.env
so they can download it. Do not ask "Does this look fine?" after writing.
That yes is the only approval. The script is not written until they say yes, so a run does not ask them to approve the mapping again and does not refuse live because a fingerprint is pending. Record the approved rows as
MAPPING_FINGERPRINT
: canonical JSON, UTF-8, keys sorted,
{"assetType":"...","rows":[{"source":"...","sentAs":"...","required":true}]}
, rows in the order shown, SHA-256 hex. That value is a record of the chat yes. It is not a second question.
Classify with the check described in their inventory. Do not classify by display name. A list that returns more than one kind of asset still yields only the type they named. The other kinds are skipped. A shared AgentCore
ListAgentRuntimes
is not permission to zip both agents and MCP. Agent script: skip
protocolConfiguration.serverProtocol=MCP
, then
GetAgentCard
or the documented synthesized card. MCP script: SigV4 JSON-RPC
initialize
, then
tools/list
; null
initialize
= skip. Name is never classification. REST script lists API Gateway (or their REST inventory), not AgentCore runtimes. A skip is a count, not a default log line: increment
skipped
and continue. Do not print
skipped {id}
,
skipping MCP
, or
not MCP
on stderr unless
--verbose
is set.
--verbose
may print
skipped {id} <reason>
. FAILED still prints (list/page errors, HTTP 401/403, missing required zip fields, upload refusals).
AgentCore MCP handshake URL is not the Exchange card field
transport.path
(
/mcp
). The invoke URL is
https://bedrock-agentcore.{region}.amazonaws.com/runtimes/{urlencoded agentRuntimeArn}/invocations?qualifier={endpointName}
.
agentRuntimeArn
comes from
get-agent-runtime
/ the list item. Encode it with
urllib.parse.quote(arn, safe="")
(every
:
,
/
, and extra character).
endpointName
is
list-agent-runtime-endpoints
runtimeEndpoints[0].name
, usually
DEFAULT
. No endpoint name means skip that runtime.
Accept
is
application/json, text/event-stream
. Parse JSON or SSE
data:
lines.
initialize
params are
protocolVersion
2025-03-26
,
capabilities
{}
,
clientInfo
. HTTP 401/403 on initialize is FAILED. HTTP 400/404/405/415/422 or a missing
result
object is skip. A generated script that POSTs
/runtimes/{agentRuntimeId}/invocations/mcp
, uses the unencoded runtime id in the path, or omits
?qualifier=
is a generation failure. A default run that prints
skipped {id}
for every non-matching runtime is a generation failure.
[GATE] 在写入文件前,必须等待用户明确回答 "Does this look fine?"。
当类型、清单、认证方式和语言均已明确时,不要在当前轮次写文件。按以下顺序展示映射,然后停止。不要把输出脚本本身视为已经展示映射。
  1. 用通俗语言说明收集到的信息:list 和 detail 调用、认证字段名称(不显示值)、语言,以及唯一的资产类型。
  2. 每个清单调用一行。列:Call、Request、Response field、Zip path。
  3. ZIP 将包含的每个字段一行。列:Source、Sent as、Required。Source 是 operation 和 response path,或
    constant
    。如果某个必填 Source 无法定位,则该行留空,并且只询问对应的 API 或字段。不要猜测。如果任何必填 Source 为空,在这里停止;不要展示第 4–8 项,也不要在所有必填 Source 填写完毕前询问
    "Does this look fine?"
    。
  4. 展示单个资产的代表性 JSON 对象。用户提供示例时使用其清单中的值,否则使用空字符串。对于
    agent
    ,每个必填 A2A v0.3 字段都要有一行(
    name
    、
    description
    、
    protocolVersion
    、
    url
    、
    version
    、
    capabilities
    、
    defaultInputModes
    、
    defaultOutputModes
    、
    skills
    )。v1 card 使用
    supportedInterfaces
    或
    supported_interfaces
    ,且没有顶层
    url
    。产物为
    a2a-card.json
    或
    a2a-v1-card.json
    。对于
    mcp
    ,产物为
    specification/mcp-metadata.json
    ,其中
    transport
    必填;如果包含 capabilities,则必须包含全部四个 boolean:
    tools
    、
    resources
    、
    prompts
    、
    logging
    ;不要添加
    serverInfo
    。对于
    rest-api
    ,产物为
    specification/oas.json
    ,其中包含
    info
    和
    paths
    ;
    externalId
    是 provider id,一个 stage 对应一个资产。
  5. 说明用户运行脚本后如何上传 ZIP:
    POST {ANYPOINT_BASE}/agent-scanner/api/v1/organizations/{org}/scanner-configurations/{config}/push
    ,请求体为 multipart part
    file
    ,文件名为
    {externalId}.zip
    。不是 JSON。结束操作是单独的
    POST .../commit
    。面向客户的问题必须是
    "Commit this scan? [y/N]"
    。不要使用
    /push-assets
    、
    /complete
    或
    /seal
    。
  6. 说明脚本架构:需要编写的函数名称(provider login、list、shape zip、token、upload、可选 commit、print status),以及下方编号 stderr 步骤。
  7. 说明 flags、环境变量、prompts,以及其中哪些是 secret。名称必须与脚本部分一致。
    --help
    使用三列:Prompt label、Parameter flag、Input file key。
  8. 逐字询问:
    "Does this look fine?"
本轮不要展示 Prerequisites 或 Ways to run the script;这些内容应在文件创建后展示。如果用户回答 no,询问哪一行有误,修正表格后再次询问,仍然不要写文件。如果用户回答 yes,则写入两个文件。文件存在后,先展示 Prerequisites,再按以下顺序展示 Ways to run the script:interactive、parameters、input file,以及完整的
inputs.env
fenced block,代码块名称为
inputs.env
,以便用户下载。写完文件后不要再询问
"Does this look fine?"
。
该 yes 是唯一批准信号。脚本在用户回答 yes 前不得编写,因此运行时不应再次要求批准映射,也不能因为 fingerprint 尚未生成而拒绝实时运行。将用户批准的各行记录为
MAPPING_FINGERPRINT
:canonical JSON、UTF-8、键排序、
{"assetType":"...","rows":[{"source":"...","sentAs":"...","required":true}]}
,各行保持展示时的顺序,使用 SHA-256 hex。该值只是对话中 yes 的记录,不是第二个问题。
按照清单中描述的检查方式进行分类。不要按 display name 分类。一个 list 返回多种资产时,仍只产出用户指定的类型,其他类型应跳过。共享的 AgentCore
ListAgentRuntimes
不表示可以同时打包 agent 和 MCP。Agent 脚本:跳过
protocolConfiguration.serverProtocol=MCP
,然后调用
GetAgentCard
或文档规定的合成 card。MCP 脚本:执行 SigV4 JSON-RPC
initialize
,然后执行
tools/list
;
initialize
返回 null 时跳过。名称绝不能作为分类依据。REST 脚本列出 API Gateway(或用户的 REST 清单),而不是 AgentCore runtimes。跳过只应计入数量,不能作为默认日志行:增加
skipped
后继续。除非设置了
--verbose
,不要在 stderr 打印
skipped {id}
、
skipping MCP
或
not MCP
。
--verbose
可以打印
skipped {id} <reason>
。FAILED 仍须打印,包括 list/page 错误、HTTP 401/403、缺少必填 ZIP 字段以及上传被拒绝。
AgentCore MCP 握手 URL 不是 Exchange card 字段
transport.path
(
/mcp
)。调用 URL 是
https://bedrock-agentcore.{region}.amazonaws.com/runtimes/{urlencoded agentRuntimeArn}/invocations?qualifier={endpointName}
。
agentRuntimeArn
来自
get-agent-runtime
或 list item。使用
urllib.parse.quote(arn, safe="")
对其编码,包括每一个
:
、
/
和其他额外字符。
endpointName
来自
list-agent-runtime-endpoints
的
runtimeEndpoints[0].name
,通常为
DEFAULT
。没有 endpoint name 时跳过该 runtime。
Accept
为
application/json, text/event-stream
。解析 JSON 或 SSE
data:
行。
initialize
的 params 包含
protocolVersion
2025-03-26
、
capabilities
{}
和
clientInfo
。initialize 返回 HTTP 401/403 时为 FAILED。HTTP 400/404/405/415/422 或缺少
result
对象时跳过。生成 POST 到
/runtimes/{agentRuntimeId}/invocations/mcp
、在路径中使用未编码 runtime id,或省略
?qualifier=
的脚本均视为生成失败。默认运行中为每个不匹配的 runtime 打印
skipped {id}
的脚本也视为生成失败。

Step 6: Write the two files

步骤 6:编写两个文件

Two files, in the language they named. No markdown guide. The chat already showed the mapping. Prerequisites and Ways to run come after these files exist.
  1. The script. One run lists the assets, checks each matching object, uploads each matching one, and then either commits the scan or stops. Zero matching assets stop after list/shape: no MuleSoft login. The asset type is a source constant (
    ASSET_TYPE
    ). The script does not accept
    --asset-type
    ,
    SCANNER_ASSET_TYPE
    , or an environment variable that switches type.
  2. An inputs file,
    inputs.env
    , written to disk beside the script and shown again as a fenced block named
    inputs.env
    so the customer can download it. The block contains the whole file. A chat that only prints the command
    --input-file inputs.env
    is a generation failure. Every secret value is empty. Non-secret placeholders are obvious fakes, never a real id from this chat. Mark each line
    (required)
    or
    (optional)
    in a comment.
Do not write a pipeline, a container, a schedule, or a second library.
inputs.env
always contains these MuleSoft lines, then the provider keys from the auth they described:
undefined
使用用户指定的语言编写两个文件。不要提供 Markdown 指南。映射已经在对话中展示;Prerequisites 和 Ways to run 应在文件存在后展示。
  1. 脚本。一次运行应列出资产、检查每个匹配对象、上传每个匹配资产,然后提交扫描或停止。零匹配资产时,在 list/shape 后停止:不进行 MuleSoft 登录。资产类型是源常量
    ASSET_TYPE
    。脚本不接受
    --asset-type
    、
    SCANNER_ASSET_TYPE
    ,也没有用于切换类型的环境变量。
  2. 输入文件
    inputs.env
    ,写在脚本旁边,并再次以名为
    inputs.env
    的 fenced block 展示完整内容,以便用户下载。代码块包含整个文件。所有 secret 值均为空。非 secret 占位值必须是明显伪造的值,绝不能使用对话中的真实 id。每一行都要在注释中标明
    (required)
    或
    (optional)
    。
不要编写 pipeline、container、schedule 或第二个 library。
inputs.env
始终先包含以下 MuleSoft 配置行,然后追加认证文档中描述的 provider 键:
undefined

(required) Anypoint host. Example: https://anypoint.mulesoft.com

(required) Anypoint host. Example: https://anypoint.mulesoft.com

ANYPOINT_BASE=
ANYPOINT_BASE=

(required) Organization id, copied from the scanner page

(required) Organization id, copied from the scanner page

ANYPOINT_ORG_ID=
ANYPOINT_ORG_ID=

(required) Scanner configuration id, copied from the scanner page

(required) Scanner configuration id, copied from the scanner page

SCANNER_CONFIGURATION_ID=
SCANNER_CONFIGURATION_ID=

(required) Connected App client id

(required) Connected App client id

ANYPOINT_CLIENT_ID=
ANYPOINT_CLIENT_ID=

(required) Connected App client secret. Leave empty in chat. Fill this on the machine that runs the script.

(required) Connected App client secret. Leave empty in chat. Fill this on the machine that runs the script.

ANYPOINT_CLIENT_SECRET=
ANYPOINT_CLIENT_SECRET=

(optional) Commit the scan without a prompt. yes or no. Default no.

(optional) Commit the scan without a prompt. yes or no. Default no.

PUSH_COMMIT=

Append one line per provider credential the script will actually ask for, with `(required)` or `(optional)`. Do not copy a credential set from a different provider. A session token, a private key, or any other long secret is `(required)` only when their auth document says the call fails without it.

When that document offers more than one credential source, ask which one before the mapping. The script uses only that source. It does not fall back to another. An attached role or a named profile is allowed when they select it. Do not demand an access key for that choice. An unattended run names the source in the inputs file. It does not guess from leftover environment variables. For AWS that line is `AWS_AUTH_MODE` with one of `profile`, `default-chain`, or `access-keys`.

The rest of this file is the script contract. Read **The script**, **One input mode**, **ZIP and push**, and `references/scanner-contract.md` before writing. Read `references/generated-script-standard.md` for stderr, JSON stdout, and the mapping fingerprint. Read `references/provider-auth-resolution.md` for managed-only auth.
PUSH_COMMIT=

为脚本实际会请求的每一个 provider credential 追加一行,并标注 `(required)` 或 `(optional)`。不要从其他 provider 复制 credential 集合。只有在认证文档说明缺少该凭据会导致调用失败时,session token、private key 或其他长期 secret 才是 `(required)`。

当认证文档提供多个 credential source 时,在展示映射前询问用户选择哪一个。脚本只能使用选定的 source,不能回退到另一个。允许使用用户选择的 role 或命名 profile。不要强制该选择必须使用 access key。无人值守运行时,应在输入文件中明确写出 source,不能从遗留环境变量中猜测。对于 AWS,该行是 `AWS_AUTH_MODE`,值为 `profile`、`default-chain` 或 `access-keys` 之一。

本文件的其余部分是脚本契约。编写前必须阅读 **The script**、**One input mode**、**ZIP and push** 和 `references/scanner-contract.md`。阅读 `references/generated-script-standard.md`,以了解 stderr、JSON stdout 和 mapping fingerprint。阅读 `references/provider-auth-resolution.md`,以了解仅托管端可执行的认证方式。

Step 7: Verify generation and show how to run

步骤 7:验证生成结果并展示运行方式

After the two files exist, show Prerequisites, then Ways to run the script in this order: interactive, parameters, input file, and the full
inputs.env
as a fenced block named
inputs.env
so they can download it. Do not ask "Does this look fine?" after writing.
Run the language checker in Same job, any language on the generated file. Search for forbidden patterns (
json=
or
"Content-Type": "application/json"
on
/push
,
POST .../seal
,
POST .../complete
,
--client-secret
,
args.[a-z]+-
). If the checker cannot run here, search the file for those patterns. Do not declare completion until the file parses in the named language and those searches are clean.
两个文件创建后,先展示 Prerequisites,再按以下顺序展示 Ways to run the script:interactive、parameters、input file,以及完整的
inputs.env
fenced block,名称为
inputs.env
,以便下载。写完文件后不要再询问
"Does this look fine?"
。
在生成的文件上运行 Same job, any language 中的语言检查器。搜索禁止模式(
/push
上使用
json=
或
"Content-Type": "application/json"
、
POST .../seal
、
POST .../complete
、
--client-secret
、
args.[a-z]+-
)。如果当前环境无法运行检查器,则在文件中搜索这些模式。在文件能够按指定语言解析且搜索结果干净之前,不要声明完成。

Connected App

Connected App

The script logs in to Anypoint with one Connected App: client id and client secret, grant
client_credentials
. It never asks for an Anypoint username or password.
An Organization Administrator creates the app once, in Access Management, before they run the script. The script cannot create it.
  1. Access Management → Connected Apps → Create App.
  2. Type: App acts on its own behalf (client credentials).
  3. Add scope
    manage:exchange
    and apply it to this organization. A token without that scope is rejected.
  4. Save. Copy the client id. Store the client secret as
    ANYPOINT_CLIENT_SECRET
    . Do not paste it into this chat.
The self-managed types are offered only when
push-scanner-enabled
is on and the entitlement matches:
agent
for agents,
apiScanners
for MCP and REST. If upload returns that the type is absent, stop and say so. Do not invent an id.
Token request, in every language:
POST {ANYPOINT_BASE}/accounts/api/v2/oauth2/token
with
Content-Type: application/x-www-form-urlencoded
and body
grant_type=client_credentials&client_id=...&client_secret=...
. Never JSON.
脚本使用一个 Connected App 登录 Anypoint:client id、client secret,以及
client_credentials
grant。绝不要求用户提供 Anypoint username 或 password。
Organization Administrator 在运行脚本前,需要先在 Access Management 中创建一次该 App。脚本无法自行创建。
  1. Access Management → Connected Apps → Create App。
  2. Type:App acts on its own behalf (client credentials)。
  3. 添加 scope
    manage:exchange
    并应用到该组织。缺少此 scope 的 token 会被拒绝。
  4. 保存。复制 client id。将 client secret 存为
    ANYPOINT_CLIENT_SECRET
    。不要粘贴到对话中。
仅当
push-scanner-enabled
已开启且 entitlement 匹配时,才提供自托管类型:agent 对应 agents,
apiScanners
对应 MCP 和 REST。如果上传返回该类型不可用,停止并说明情况。不要编造 id。
每种语言中的 token 请求均为:
POST {ANYPOINT_BASE}/accounts/api/v2/oauth2/token
,使用
Content-Type: application/x-www-form-urlencoded
,请求体为
grant_type=client_credentials&client_id=...&client_secret=...
。绝不能使用 JSON。

What the script does

脚本执行过程

Inside that one run the script prints a numbered step banner on stderr only when that step runs, then stops. Do not split them across programs. Do not print a later banner after the run has stopped.
── Step 1: provider login
── Step 2: list assets
── Step 3: shape zips
── Step 4: MuleSoft login
── Step 5: publish
── Step 6: commit
--dry-run
stops after step 3. There is no MuleSoft login and no secret prompt. That skip is success.
After step 3, if zero assets matched
ASSET_TYPE
:
  • Print
    No matching {ASSET_TYPE} assets found.
    on stderr (
    agent
    ,
    mcp
    , or
    rest-api
    ).
  • Print the JSON object on stdout (
    ok
    true, that type's count
    0
    ,
    skipped
    for classified-away and handshake skips, empty publish ids).
  • Exit 0.
  • Do not print Step 4, 5, or 6. Do not prompt for the Connected App secret. Do not call
    /push
    or
    /commit
    .
  • --dry-run
    uses this same stop.
  • Live exception only:
    PUSH_ALLOW_EMPTY=yes
    continues to
    GET .../workspace
    and the empty-commit path in step 5.
  1. Read inputs. See One input mode.
  2. Call their list and detail APIs with their auth. Follow pages until the list ends or a page cap is hit. If the list call itself fails, exit 2 and do not commit. After a successful list, print one summary line:
    listed N, matching M, skipped K
    . Do not print one line per skipped id unless
    --verbose
    .
  3. For each matching asset, build the object from the mapping they accepted. If a required field is missing, print FAILED and do not upload that object. An invalid object is the script's fault. Print each matching asset on its own line: type, external id, display name. Print the zip path
    {id}/specification/config.json
    plus the artifact. A zip that uses
    {id}/config.json
    (no
    specification/
    ) is a generation failure.
  4. Upload each valid ZIP with
    POST {ANYPOINT_BASE}/agent-scanner/api/v1/organizations/{org}/scanner-configurations/{config}/push
    . The body is the zip bytes, not JSON.
    Content-Type
    is
    multipart/form-data
    with exactly one part named
    file
    , filename
    {externalId}.zip
    , part
    Content-Type: application/zip
    . HTTP 202 JSON is
    {assetId, action, workspaceRunId}
    . Keep that
    workspaceRunId
    . Every later upload in this run must return the same id. The server checks the zip again. A refusal is FAILED, with the response body. The same provider id replaces the staged object. It does not create a second row, and Exchange is not called. An id uploaded earlier and absent from this list stays staged until
    DELETE .../push/{externalId}
    . Omission is not deletion. HTTP 415 means this POST was not a zip part named
    file
    (JSON body,
    application/x-www-form-urlencoded
    ,
    Content-Type: multipart/form-data
    with no boundary, or a boundary that starts with
    =
    ). A generated script that posts JSON to
    /push
    , uses
    json=
    , sets
    Content-Type: application/json
    on
    /push
    , or names the part anything other than
    file
    is a generation failure.
  5. Close the workspace and declare completeness separately.
    workspaceRunId
    comes only from a 202
    /push
    (or
    GET .../workspace
    when
    PUSH_ALLOW_EMPTY=yes
    and nothing was uploaded). Inventing
    run-…
    or posting
    /commit
    without that id is a generation failure. Zero accepted uploads: do not call
    /commit
    .
    • The list stopped at a page cap, or any upload failed, and at least one upload was accepted:
      POST .../commit
      with
      {"workspaceRunId":"<id from 202>","complete":false}
      . Do not ask.
      complete:false
      is upsert only. It must not be
      true
      .
    • The list finished and every upload succeeded: ask on a TTY, "Commit this scan? [y/N]". The default is no.
      --commit
      or
      PUSH_COMMIT=yes
      is the yes when there is no TTY. Yes sends
      POST .../commit
      with
      "complete":true
      . No uploads and does not commit.
    • An empty successful list does not commit unless they also set
      PUSH_ALLOW_EMPTY=yes
      .
  6. Print one JSON object on stdout: counts,
    truncated
    ,
    workspaceRunId
    ,
    scanRunId
    , and whether the scan was committed. Exit 0 when nothing failed. Exit 2 when a list, an upload, or a requested commit failed.
complete: true
means this list is the full inventory, so the scanner may retire assets that were not in the list.
complete: false
means upsert only.
The upload is one ZIP per asset because that is the API. The customer confirms the mapping and the sample JSON. Do not spend the chat on archive layout. The script still produces a valid ZIP: one directory whose name is the provider's stable id,
specification/config.json
with
name
and
type
, and the artifact next to it (
a2a-card.json
or
a2a-v1-card.json
,
mcp-metadata.json
, or
oas.json
).
Live stderr after MuleSoft values resolve (non-secrets in full; secret presence only):
Anypoint host: https://anypoint.mulesoft.com
Anypoint Organization ID: …
Scanner Configuration ID: …
Connected App Client ID: …
Connected App Client Secret: set
Ask only the missing ones.
--dry-run
must not prompt for those Anypoint rows.
在一次运行中,脚本仅在步骤实际执行时向 stderr 打印编号步骤横幅,然后停止。不要把步骤拆成多个程序。运行停止后,不要打印后续步骤的横幅。
── Step 1: provider login
── Step 2: list assets
── Step 3: shape zips
── Step 4: MuleSoft login
── Step 5: publish
── Step 6: commit
--dry-run
在步骤 3 后停止。不进行 MuleSoft 登录,也不提示 secret。该跳过属于成功。
步骤 3 后,如果匹配
ASSET_TYPE
的资产数为零:
  • 在 stderr 打印
    No matching {ASSET_TYPE} assets found.
    (
    agent
    、
    mcp
    或
    rest-api
    )。
  • 在 stdout 打印 JSON 对象(
    ok
    为 true,该类型计数为
    0
    ,
    skipped
    包含分类排除和握手跳过项,publish ids 为空)。
  • 退出码为 0。
  • 不打印步骤 4、5、6。不提示 Connected App secret。不调用
    /push
    或
    /commit
    。
  • --dry-run
    使用相同的停止逻辑。
  • 唯一的实时例外是:
    PUSH_ALLOW_EMPTY=yes
    时继续执行
    GET .../workspace
    ,并进入步骤 5 的空提交路径。
  1. 读取输入。参见 One input mode。
  2. 使用认证方式调用客户的 list 和 detail API。持续翻页,直到 list 结束或达到 page cap。如果 list 调用本身失败,退出码为 2,并且不要提交。成功 list 后,打印一行摘要:
    listed N, matching M, skipped K
    。除非使用
    --verbose
    ,不要为每个被跳过的 id 打印一行。
  3. 对每个匹配资产,使用客户批准的 mapping 构建对象。如果缺少必填字段,打印 FAILED,并且不上传该对象。无效对象属于脚本错误。每个匹配资产单独打印一行:type、external id、display name。打印 ZIP 路径
    {id}/specification/config.json
    以及产物。使用
    {id}/config.json
    (没有
    specification/
    )的 ZIP 属于生成失败。
  4. 使用
    POST {ANYPOINT_BASE}/agent-scanner/api/v1/organizations/{org}/scanner-configurations/{config}/push
    上传每个有效 ZIP。请求体是 ZIP 字节,不是 JSON。
    Content-Type
    为
    multipart/form-data
    ,且只能有一个名为
    file
    的 part,文件名为
    {externalId}.zip
    ,part 的
    Content-Type
    为
    application/zip
    。HTTP 202 JSON 为
    {assetId, action, workspaceRunId}
    。保留该
    workspaceRunId
    。本次运行中的每次后续上传都必须返回同一个 id。服务器会再次检查 ZIP。上传被拒绝时打印 FAILED,并附上响应体。相同 provider id 会替换暂存对象,不会创建第二行,也不会调用 Exchange。本次 list 中未包含的早期上传 id 会保持暂存,直到调用
    DELETE .../push/{externalId}
    。遗漏并不表示删除。HTTP 415 表示该 POST 没有收到名为
    file
    的 ZIP part,例如使用了 JSON body、
    application/x-www-form-urlencoded
    、
    Content-Type: multipart/form-data
    但没有 boundary,或者 boundary 以
    =
    开头。生成向
    /push
    POST JSON、使用
    json=
    、在
    /push
    上设置
    Content-Type: application/json
    ,或使用
    file
    以外 part 名称的脚本均视为生成失败。
  5. 分别关闭 workspace 并声明完整性。
    workspaceRunId
    只能来自 HTTP 202 的
    /push
    响应;当
    PUSH_ALLOW_EMPTY=yes
    且没有上传任何内容时,可以来自
    GET .../workspace
    。编造
    run-…
    ,或在缺少该 id 的情况下 POST
    /commit
    ,均视为生成失败。没有成功接受任何上传时,不要调用
    /commit
    。
    • list 在 page cap 处停止,或任一上传失败,但至少有一个上传成功被接受:POST
      .../commit
      ,请求体为
      {"workspaceRunId":"<id from 202>","complete":false}
      。不要询问。
      complete:false
      表示只执行 upsert,绝不能为
      true
      。
    • list 完整结束且所有上传都成功:在 TTY 上询问
      "Commit this scan? [y/N]"
      。默认值为 no。没有 TTY 时,
      --commit
      或
      PUSH_COMMIT=yes
      表示 yes。Yes 发送 POST
      .../commit
      ,其中
      "complete":true
      。No 不上传,也不提交。
    • 成功得到空 list 时,除非同时设置
      PUSH_ALLOW_EMPTY=yes
      ,否则不要提交。
  6. 在 stdout 打印一个 JSON 对象:包含计数、
    truncated
    、
    workspaceRunId
    、
    scanRunId
    ,以及扫描是否已提交。没有失败时退出码为 0。list、上传或用户请求的提交失败时,退出码为 2。
complete: true
表示该 list 是完整 inventory,因此 scanner 可以退役未出现在 list 中的资产。
complete: false
表示仅执行 upsert。
API 要求每个资产上传一个 ZIP。客户需要确认 mapping 和示例 JSON。不要在对话中花费大量时间讨论 archive 布局。脚本仍必须生成有效 ZIP:一个以 provider 稳定 id 命名的目录、
specification/config.json
(包含
name
和
type
),以及与其同级的产物(
a2a-card.json
或
a2a-v1-card.json
、
mcp-metadata.json
或
oas.json
)。
MuleSoft 值解析完成后,实时 stderr 应显示如下内容(非 secret 显示完整值,secret 只显示是否存在):
Anypoint host: https://anypoint.mulesoft.com
Anypoint Organization ID: …
Scanner Configuration ID: …
Connected App Client ID: …
Connected App Client Secret: set
只询问缺少的值。
--dry-run
不得提示任何 Anypoint 配置项。

One input mode

One input mode

One run uses one value source. Control flags do not pick a source and do not block prompts. Control flags are
--help
,
--dry-run
,
--verbose
, and
--commit
. Provider fields come from the authentication document they pasted, minus pull-scanner-only hub/spoke fields. AWS, Azure, GCP, Databricks, Snowflake, Kong, and a provider that is not in the catalog use that same rule. Do not copy an AWS field onto another provider.
Inside the chosen source, every field uses this fill order. A variable already in the shell fills the value. It does not switch the source, and a blank prompt must not erase it.
  1. Command flag already set → use it. Do not prompt.
  2. Else the environment variable.
  3. Else the
    --input-file
    /
    PUSH_INPUT_FILE
    key, when that source is the input file.
  4. Else a TTY prompt in this same process. Hide a secret. An empty answer keeps step 2.
  5. Else, not a TTY →
    FAILED
    naming the missing input.
Three ways to supply values. They are OR.
  1. Input file.
    --input-file
    or
    PUSH_INPUT_FILE
    is set. Every required value, including secrets, is in that file. A missing required key is FAILED.
    --dry-run
    and
    --commit
    may be added. They do not switch the run to parameters mode.
  2. Parameters. A value flag is on the command line, and no input file is set. Value flags are
    --anypoint-base
    ,
    --org
    ,
    --config
    ,
    --client-id
    , then only that provider's flags. AWS adds
    --profile
    and
    --region
    /
    --aws-region
    . Azure and GCP do not get
    --profile
    . Secrets are environment variables, never flags. A missing required value is FAILED. No prompt.
  3. Prompts. No input file and no value flag, and stdin is a TTY.
    --dry-run
    alone is this mode. Ask only for a label that is still empty after the environment. A secret already in the environment is not asked again.
--dry-run
does not call the scanner. It does not require the Anypoint host, organization id, configuration id, client id, or client secret. It still needs the provider credentials that list the assets.
No file, no value flag, and no TTY → FAILED naming the missing input.
一次运行只使用一个 value source。Control flags 不会选择 source,也不会阻止 prompts。Control flags 为
--help
、
--dry-run
、
--verbose
和
--commit
。Provider 字段来自用户粘贴的认证文档,并排除仅供 pull scanner 使用的 hub/spoke 字段。AWS、Azure、GCP、Databricks、Snowflake、Kong 以及不在 catalog 中的 provider 均遵循同一规则。不要把 AWS 字段复制到其他 provider。
在选定的 source 内,每个字段都按以下顺序填充。Shell 中已存在的变量会提供值,但它不会切换 source;空白 prompt 也不能清除它。
  1. 命令行 flag 已设置 → 使用该值。不要提示。
  2. 否则使用环境变量。
  3. 否则,当 source 为 input file 时,使用
    --input-file
    /
    PUSH_INPUT_FILE
    中对应的键。
  4. 否则,在同一进程中通过 TTY 提示输入。Secret 必须隐藏。空回答保留步骤 2 的值。
  5. 否则,若不是 TTY → 打印
    FAILED
    ,并指明缺少的输入。
提供值有三种方式,三者互斥。
  1. Input file。 设置了
    --input-file
    或
    PUSH_INPUT_FILE
    。所有必填值,包括 secret,都放在该文件中。缺少必填键时为 FAILED。可附加
    --dry-run
    和
    --commit
    ,它们不会让运行切换到 parameters 模式。
  2. Parameters。 命令行中存在 value flag,且未设置 input file。Value flags 依次为
    --anypoint-base
    、
    --org
    、
    --config
    、
    --client-id
    ,然后仅追加该 provider 的 flags。AWS 增加
    --profile
    和
    --region
    /
    --aws-region
    。Azure 和 GCP 不使用
    --profile
    。Secret 只能通过环境变量提供,不能作为 flag。缺少必填值时为 FAILED,不进行提示。
  3. Prompts。 没有 input file,也没有 value flag,并且 stdin 是 TTY。单独的
    --dry-run
    也属于此模式。只询问在检查环境变量后仍为空的 label。环境中已经存在的 secret 不再询问。
--dry-run
不调用 scanner。它不要求提供 Anypoint host、organization id、configuration id、client id 或 client secret,但仍需要用于列出资产的 provider credentials。
没有文件、没有 value flag,并且不是 TTY → 打印 FAILED,并指明缺少的输入。

Pull-form provider login

Pull-form provider login

Step 1 looks like the Exchange connection form for that provider, not a cloud-CLI tutorial. Derive prompts from the authentication document they pasted. If a current pull form matches that provider, use that credential class's
@Field(label=...)
for the fields the script actually asks. Do not copy an AWS, Azure, or Kong field set onto a different provider. Do not send any of these values to MuleSoft. The push configuration is
authScheme=customer-upload
with no
authParameters
.
Pull scanner form (UI label)Script promptSecret?
AWS Access Key ID
AWS Access Key ID
no
AWS Secret Access Key
AWS Secret Access Key
yes
AWS Session Tokenhidden, only when the access key is
ASIA
after stripping quotes and the token is not already in the environment or the input file
yes
AWS Region
AWS Region
no
Tenant ID / Client ID / Client Secret (Azure)same labelssecret last
Subscription ID (Azure APIM)same labelno
Personal Access Token (Kong)same labelyes
GCP Project ID / Service Account Email / Private Keysame labelsprivate key yes
Workspace URL + client id/secret (Databricks)same labelssecret yes
Do not prompt Hub Role ARN, Spoke Role Name, External ID, Account IDs, or Target Regions. Those names exist on the pull scanner form. This script does not assume a role. A
--help
row labeled Hub Role ARN, Spoke Role Name, External ID, Account IDs, or Target Regions is a generation failure.
步骤 1 应类似于该 provider 的 Exchange connection form,而不是云 CLI 教程。根据用户粘贴的认证文档推导 prompts。如果当前 pull form 与该 provider 匹配,应对脚本实际询问的字段使用该 credential class 的
@Field(label=...)
。不要把 AWS、Azure 或 Kong 的字段集合复制给其他 provider。不要将这些值发送给 MuleSoft。Push 配置为
authScheme=customer-upload
,且没有
authParameters
。
Pull scanner form(UI label)Script promptSecret?
AWS Access Key ID
AWS Access Key ID
否
AWS Secret Access Key
AWS Secret Access Key
是
AWS Session Token隐藏;仅当去除引号后的 access key 以
ASIA
开头,且 token 尚未存在于环境或 input file 中时询问
是
AWS Region
AWS Region
否
Tenant ID / Client ID / Client Secret (Azure)相同 label最后一项为 secret
Subscription ID (Azure APIM)相同 label否
Personal Access Token (Kong)相同 label是
GCP Project ID / Service Account Email / Private Key相同 labelprivate key 为 secret
Workspace URL + client id/secret (Databricks)相同 labelsecret 为是
不要提示 Hub Role ARN、Spoke Role Name、External ID、Account IDs 或 Target Regions。这些名称存在于 pull scanner form 中,但本脚本不假定 role。带有这些名称的
--help
行属于生成失败。

Already logged in

已登录状态

The laptop CLI/SDK session is the default. Access keys, client secrets, and private keys are the other branch.
  • AWS.
    ~/.aws/config
    /
    ~/.aws/credentials
    already work.
    --help
    must have the row
    AWS Profile | --profile | AWS_PROFILE
    .
    --profile NAME
    uses that profile and does not ask for Access Key, Secret, or Session Token.
    --profile
    /
    AWS_PROFILE
    wins over leftover
    AWS_ACCESS_KEY_ID
    /
    AWS_SECRET_ACCESS_KEY
    in the environment. Do not tell them to
    export AWS_PROFILE
    . On a TTY, AWS Access Key ID first. Blank, and
    --profile
    /
    AWS_PROFILE
    already set: do not ask Secret. Blank, and no profile yet: prompt AWS Profile (empty = default chain already on this machine), then AWS Region only. Non-TTY:
    --profile
    ,
    AWS_AUTH_MODE=default-chain
    , or access keys. Blank Access Key with none of those is FAILED; do not silently call STS on leftover environment credentials or a default chain they did not choose. An AWS
    --help
    that lists Access Key and Region but never
    --profile
    /
    AWS_PROFILE
    is a generation failure.
  • Azure.
    az
    is already logged in. Use that session (DefaultAzureCredential /
    az account
    ). Do not add
    --profile
    . Do not prompt Tenant ID, Client ID, or Client Secret unless they pasted those as the auth document they will actually use.
  • GCP.
    gcloud
    is already logged in (ADC). Use that session. Do not add
    --profile
    . Do not prompt Service Account Email or Private Key unless they pasted the service-account JSON as the auth they will actually use.
  • Kong, Databricks, Snowflake, Claude, LangSmith. No analog of
    aws/config
    . Use that provider's token fields. Do not invent
    --profile
    .
--profile
is AWS only. A
--help
row
--profile
on Azure, GCP, Kong, or Databricks is a generation failure.
默认使用笔记本上的 CLI/SDK session。Access keys、client secrets 和 private keys 属于另一种认证分支。
  • AWS。
    ~/.aws/config
    /
    ~/.aws/credentials
    已经可用。
    --help
    必须包含
    AWS Profile | --profile | AWS_PROFILE
    这一行。使用
    --profile NAME
    时采用该 profile,不询问 Access Key、Secret 或 Session Token。
    --profile
    /
    AWS_PROFILE
    的优先级高于环境中遗留的
    AWS_ACCESS_KEY_ID
    /
    AWS_SECRET_ACCESS_KEY
    。不要要求用户执行
    export AWS_PROFILE
    。在 TTY 上,首先询问 AWS Access Key ID。输入为空且已设置
    --profile
    /
    AWS_PROFILE
    时,不要询问 Secret。输入为空且尚无 profile 时,提示 AWS Profile(留空表示使用本机已有的 default chain),然后仅提示 AWS Region。非 TTY:必须使用
    --profile
    、
    AWS_AUTH_MODE=default-chain
    或 access keys。Access Key 为空且以上选项均未设置时为 FAILED;不能静默使用遗留的环境凭据或用户未选择的 default chain 调用 STS。AWS 的
    --help
    如果列出 Access Key 和 Region,却从未列出
    --profile
    /
    AWS_PROFILE
    ,则属于生成失败。
  • Azure。
    az
    已经登录。使用该 session(DefaultAzureCredential /
    az account
    )。不要添加
    --profile
    。除非用户粘贴了实际使用的认证文档,否则不要提示 Tenant ID、Client ID 或 Client Secret。
  • GCP。
    gcloud
    已经登录(ADC)。使用该 session。不要添加
    --profile
    。除非用户粘贴了 service-account JSON 作为实际使用的认证方式,否则不要提示 Service Account Email 或 Private Key。
  • Kong、Databricks、Snowflake、Claude、LangSmith。 没有类似
    aws/config
    的机制。使用对应 provider 的 token 字段。不要自行创建
    --profile
    。
--profile
仅适用于 AWS。在 Azure、GCP、Kong 或 Databricks 的
--help
中列出
--profile
属于生成失败。

AWS login

AWS 登录

AWS asks for one login, then the region. Nothing else. Order on a TTY: AWS Access Key ID, then either the already-logged-in profile path above, or AWS Secret Access Key (hidden) when the key is non-empty, then AWS Session Token (hidden) only when the unquoted key starts with
ASIA
and the token is not already set, then AWS Region. Skipping Access Key ID and jumping to Secret is a generation failure.
  • Access keys:
    AWS_ACCESS_KEY_ID
    and
    AWS_SECRET_ACCESS_KEY
    from the flag/env/file/prompt. Strip wrapping quotes, including
    “”‘’
    , before an
    ASIA
    check. A check on the raw prompt string is a generation failure. Pass the unquoted key, secret, and token into boto3 together. Do not leave a leftover
    AWS_SESSION_TOKEN
    in the process environment. If the key is
    ASIA
    and the token is still empty,
    FAILED
    names
    AWS_SESSION_TOKEN
    before any AWS call.
  • Region:
    --region
    /
    --aws-region
    /
    AWS_REGION
    . One region. Do not ask for a second region list.
--help
provider rows for AWS are only
--profile
, the access-key pair (secret has no flag), and
--region
/
--aws-region
.
Required unquote (or the same behavior in the language they named):
python
def _unquote_aws(value):
    text = (value or "").strip()
    marks = "\"'" + "\u201c\u201d\u2018\u2019"
    while len(text) >= 2 and text[0] in marks and text[-1] in marks:
        text = text[1:-1].strip()
    return text
ASIA check is
_unquote_aws(ack).upper().startswith("ASIA")
. After writing, search the script for
startswith("ASIA")
applied to the raw prompt string. Any such match is a generation failure.
AWS inventory paths such as
/ListAgentRuntimes
are boto3 operation names. They are not URLs. Call
boto3.client("bedrock-agentcore-control").list_agent_runtimes
and
boto3.client("bedrock-agentcore").get_agent_card
. A handwritten SigV4 request, a POST to
https://bedrock-agentcore-control.../ListAgentRuntimes
, or
Content-Type: application/x-amz-json-1.1
without the AWS SDK is a generation failure. The 403 body
Unable to determine service/operation name to be authorized
means that mistake.
--region us-east-1 --profile scanner
must reach STS as region
us-east-1
and profile
scanner
. Do not prompt AWS Secret Access Key when Access Key ID is blank and
--profile
is set. Nested Bash
${CLI_REGION:-${AWS_REGION:-x}}}}
is a generation failure (
us-east-1}
). Sequential assignments only. After writing a
.sh
, search for
}}}}
and
--region ${
.
AWS 先询问一次登录信息,然后询问 region,不询问其他内容。TTY 上的顺序为:AWS Access Key ID,然后选择已登录 profile 路径,或在 key 非空时输入 AWS Secret Access Key(隐藏),仅当去除引号后的 key 以
ASIA
开头且 token 尚未设置时输入 AWS Session Token(隐藏),最后输入 AWS Region。跳过 Access Key ID 而直接询问 Secret 属于生成失败。
  • Access keys:从 flag/env/file/prompt 获取
    AWS_ACCESS_KEY_ID
    和
    AWS_SECRET_ACCESS_KEY
    。在检查
    ASIA
    前,必须去除包裹引号,包括
    “”‘’
    。直接对原始 prompt 字符串执行检查属于生成失败。将去除引号后的 key、secret 和 token 一起传给 boto3。不要在进程环境中遗留
    AWS_SESSION_TOKEN
    。如果 key 以
    ASIA
    开头且 token 仍为空,在调用 AWS 之前打印 FAILED,并指出
    AWS_SESSION_TOKEN
    。
  • Region:
    --region
    /
    --aws-region
    /
    AWS_REGION
    。只允许一个 region。不要询问第二份 region 列表。
--help
中的 AWS provider 行只能包括
--profile
、access-key 对(secret 没有 flag),以及
--region
/
--aws-region
。
必须执行 unquote,或在用户指定语言中实现同等行为:
python
def _unquote_aws(value):
    text = (value or "").strip()
    marks = "\"'“”‘’"
    while len(text) >= 2 and text[0] in marks and text[-1] in marks:
        text = text[1:-1].strip()
    return text
ASIA 检查方式为
_unquote_aws(ack).upper().startswith("ASIA")
。写完后,在脚本中搜索对原始 prompt 字符串执行的
startswith("ASIA")
。任何匹配都属于生成失败。
/ListAgentRuntimes
等 AWS inventory path 是 boto3 operation 名称,不是 URL。调用
boto3.client("bedrock-agentcore-control").list_agent_runtimes
和
boto3.client("bedrock-agentcore").get_agent_card
。手写 SigV4 请求、向
https://bedrock-agentcore-control.../ListAgentRuntimes
发送 POST,或者在没有 AWS SDK 时使用
Content-Type: application/x-amz-json-1.1
,均属于生成失败。403 响应正文
Unable to determine service/operation name to be authorized
意味着出现了此类错误。
--region us-east-1 --profile scanner
必须让 STS 接收 region
us-east-1
和 profile
scanner
。当 Access Key ID 为空且设置了
--profile
时,不要提示 AWS Secret Access Key。嵌套 Bash
${CLI_REGION:-${AWS_REGION:-x}}}}
属于生成失败(
us-east-1]}
)。只能顺序赋值。写完
.sh
后,搜索
}}}}
和
--region ${
。

The script

脚本

Flags, same spelling in every language:
--dry-run
,
--input-file
,
--anypoint-base
,
--org
,
--config
,
--client-id
,
--commit
,
--verbose
,
--help
. There is no
--asset-type
and no
--client-secret
.
--profile
is AWS only.
--region
/
--aws-region
is only when that provider uses a region. Other provider flags come from their auth document.
--help
exits 0 and shows three columns for every input, in this order of ways to supply it: Prompt label, Parameter flag, Input file key. Connected App fields first, then the already-logged-in row for that cloud if it has one (
AWS Profile
/
az
/
gcloud
), then the fields from their auth document. The client secret has no flag. Help explains
--dry-run
and
--commit
. A
--help
that lists
--client-id
but never mentions Connected App Client Secret or
ANYPOINT_CLIENT_SECRET
is a generation failure. Copy this into argparse
epilog
/ usage:
Inputs and where to obtain them:
  --anypoint-base / ANYPOINT_BASE: Anypoint host. Scanner path is that host plus /agent-scanner.
    Example US production: https://anypoint.mulesoft.com
  --org / ANYPOINT_ORG_ID: organization id from the Exchange scanner page
  --config / SCANNER_CONFIGURATION_ID: configuration id from that same page
  --client-id / ANYPOINT_CLIENT_ID: Connected App Client ID
  Connected App Client Secret: ANYPOINT_CLIENT_SECRET, matching --input-file key, or hidden
    prompt labeled "Connected App Client Secret". Never a process argument. No --client-secret.
AWS scripts also:
  --profile / AWS_PROFILE: AWS Profile. Already logged in via ~/.aws/config. Wins over leftover
    AWS_ACCESS_KEY_ID. Not an Azure or GCP flag.
  AWS Access Key ID: AWS_ACCESS_KEY_ID or prompt. Blank uses --profile / the default chain.
  AWS Secret Access Key: AWS_SECRET_ACCESS_KEY or hidden prompt. No flag. Skip when Access Key
    is blank and --profile or the default chain is in use.
  --region / --aws-region / AWS_REGION: AWS Region
Azure scripts: az already logged in (DefaultAzureCredential). Do not add --profile.
GCP scripts: gcloud already logged in (ADC). Do not add --profile.
Python argparse dests use underscores (
args.anypoint_base
).
args.approve-mapping
is a generation failure. After writing, search the script for
args.[a-z]+-
. Any match is a failure.
--dry-run
builds the objects on disk and does not call the scanner. It does not commit. It does not prove the server will accept the object. The server check happens on upload. Say that in the help text and in Ways to run the script.
A generated script that posts to
localhost
,
127.0.0.1
, a laptop port, or any URL other than
{ANYPOINT_BASE}/agent-scanner
is a generation failure. There is no
--scanner-base
and no
SCANNER_BASE
.
所有语言中的 flags 拼写一致:
--dry-run
、
--input-file
、
--anypoint-base
、
--org
、
--config
、
--client-id
、
--commit
、
--verbose
、
--help
。不存在
--asset-type
和
--client-secret
。
--profile
仅适用于 AWS。仅当 provider 使用 region 时才使用
--region
/
--aws-region
。其他 provider flags 来自其认证文档。
--help
退出码为 0,并按输入来源顺序为每个输入显示三列:Prompt label、Parameter flag、Input file key。首先显示 Connected App 字段,然后显示该云平台对应的已登录行(如果有:
AWS Profile
/
az
/
gcloud
),最后显示认证文档中的字段。Client secret 没有 flag。Help 应说明
--dry-run
和
--commit
。如果
--help
列出了
--client-id
,却从未提到 Connected App Client Secret 或
ANYPOINT_CLIENT_SECRET
,则属于生成失败。将以下内容复制到 argparse
epilog
/ usage:
Inputs and where to obtain them:
  --anypoint-base / ANYPOINT_BASE: Anypoint host. Scanner path is that host plus /agent-scanner.
    Example US production: https://anypoint.mulesoft.com
  --org / ANYPOINT_ORG_ID: organization id from the Exchange scanner page
  --config / SCANNER_CONFIGURATION_ID: configuration id from that same page
  --client-id / ANYPOINT_CLIENT_ID: Connected App Client ID
  Connected App Client Secret: ANYPOINT_CLIENT_SECRET, matching --input-file key, or hidden
    prompt labeled "Connected App Client Secret". Never a process argument. No --client-secret.
AWS scripts also:
  --profile / AWS_PROFILE: AWS Profile. Already logged in via ~/.aws/config. Wins over leftover
    AWS_ACCESS_KEY_ID. Not an Azure or GCP flag.
  AWS Access Key ID: AWS_ACCESS_KEY_ID or prompt. Blank uses --profile / the default chain.
  AWS Secret Access Key: AWS_SECRET_ACCESS_KEY or hidden prompt. No flag. Skip when Access Key
    is blank and --profile or the default chain is in use.
  --region / --aws-region / AWS_REGION: AWS Region
Azure scripts: az already logged in (DefaultAzureCredential). Do not add --profile.
GCP scripts: gcloud already logged in (ADC). Do not add --profile.
Python argparse dest 使用下划线(
args.anypoint_base
)。
args.approve-mapping
属于生成失败。写完后在脚本中搜索
args.[a-z]+-
,任何匹配都属于失败。
--dry-run
在磁盘上构建对象,但不调用 scanner,也不提交。它不能证明服务器会接受该对象;服务器检查发生在上传时。应在 help text 和 Ways to run the script 中说明这一点。
向
localhost
、
127.0.0.1
、笔记本端口,或
{ANYPOINT_BASE}/agent-scanner
以外任何 URL 发送请求的脚本属于生成失败。不存在
--scanner-base
和
SCANNER_BASE
。

Ways to run the script

运行脚本的方式

After the two files exist, the chat shows this section in this order, then it stops: interactive, then parameters, then the input file. The command is whatever runs the file they asked for. Do not show a Python, Bash, Java, or Go command unless that is the language they named. The blocks below use
<run> <script>
as the shape.
--help
uses the same three columns: prompt label, parameter flag, input file key.
两个文件创建后,聊天按以下顺序展示本节,然后停止:interactive、parameters、input file。命令必须是运行用户指定文件的命令。除非用户指定了相应语言,否则不要展示 Python、Bash、Java 或 Go 命令。下方代码块使用
<run> <script>
作为结构。
--help
使用相同的三列:prompt label、parameter flag、input file key。

Prerequisites

前置条件

  • The language runtime they named is installed, including any library their auth document requires.
  • A Connected App client id and secret, as in Connected App.
  • The organization id and the configuration id, copied from the self-managed scanner page. The script does not look these up and does not create them.
  • The provider session: already logged in (
    --profile
    /
    ~/.aws/config
    on AWS,
    az
    on Azure,
    gcloud
    on GCP) or the credentials from their auth document, stored as environment variables or in the inputs file. Not in the chat. Not on the command line.
  • 已安装用户指定的语言 runtime,包括认证文档要求的任何 library。
  • 一个 Connected App client id 和 secret,详见 Connected App。
  • 从自托管 scanner 页面复制的 organization id 和 configuration id。脚本不会查询这些值,也不会创建它们。
  • Provider session:已经登录(AWS 使用
    --profile
    /
    ~/.aws/config
    ,Azure 使用
    az
    ,GCP 使用
    gcloud
    ),或使用认证文档中的 credentials,并存放在环境变量或输入文件中。不能放在对话里,也不能放在命令行上。

Prompts

Prompts

<run> <script>
The script asks once for each required value that is still empty, then uploads. At the end it asks "Commit this scan? [y/N]". Pressing Enter means no.
<run> <script>
脚本对每个仍为空的必填值询问一次,然后开始上传。最后询问
"Commit this scan? [y/N]"
。按 Enter 表示 no。

Parameters

Parameters

export ANYPOINT_CLIENT_SECRET="..."
export PROVIDER_SECRET="..."
<run> <script> \
  --anypoint-base https://anypoint.mulesoft.com \
  --org YOUR_ORG_ID \
  --config YOUR_CONFIGURATION_ID \
  --client-id YOUR_CLIENT_ID \
  --commit
--commit
answers yes. Without it, the script uploads and does not commit. Secret names match their auth document.
PROVIDER_SECRET
above is a placeholder for that name. For AWS already logged in on this machine, add
--profile NAME --region us-east-1
instead of access-key exports.
export ANYPOINT_CLIENT_SECRET="..."
export PROVIDER_SECRET="..."
<run> <script> \
  --anypoint-base https://anypoint.mulesoft.com \
  --org YOUR_ORG_ID \
  --config YOUR_CONFIGURATION_ID \
  --client-id YOUR_CLIENT_ID \
  --commit
--commit
表示 yes。不使用它时,脚本会上传但不提交。Secret 名称应与认证文档一致。上面的
PROVIDER_SECRET
是对应名称的占位符。对于本机已登录的 AWS,应改为添加
--profile NAME --region us-east-1
,而不是导出 access key。

Input file

Input file

The file
inputs.env
is a downloadable file, written beside the script, and its full text is in the chat as a block named
inputs.env
. They fill the empty secrets on the machine that runs the script, then:
<run> <script> --input-file inputs.env
PUSH_COMMIT=yes
in that file commits the scan. Empty or
no
does not.
inputs.env
是可下载文件,写在脚本旁边,并在聊天中以名为
inputs.env
的代码块展示完整文本。用户应在运行脚本的机器上填写空缺 secret,然后执行:
<run> <script> --input-file inputs.env
文件中的
PUSH_COMMIT=yes
表示提交扫描。留空或
no
表示不提交。

Dry-run and help

Dry-run 和 help

<run> <script> --help
<run> <script> --dry-run
<run> <script> --input-file inputs.env --dry-run
--help
lists the inputs.
--dry-run
writes the objects locally and does not contact the scanner.
<run> <script> --help
<run> <script> --dry-run
<run> <script> --input-file inputs.env --dry-run
--help
列出输入项。
--dry-run
在本地写入对象,不联系 scanner。

Failures

失败处理

Every failure prints this on stderr and exits 2:
FAILED step=<name> http=<code>
where: <call>
request: <method and path, no secrets>
response fields: <names only>
why: <one sentence>
body: <response snippet with secrets removed>
next: <what to fix>
Do not print only
HTTP Error 503:
or a traceback.
httpwhynext
0 / connection refusedCannot reach that Anypoint host.Confirm
--anypoint-base
/
ANYPOINT_BASE
is reachable. Token and push both use
{that host}/agent-scanner
.
401 / 403Connected App rejected. Wrong secret, or missing
manage:exchange
on this organization.
Reset the secret on the same app as the client id. Scope it to this org.
404Org id, configuration id, or
/agent-scanner
path is wrong on this Anypoint host.
Stay on
{ANYPOINT_BASE}/agent-scanner
. Copy both ids from the Exchange scanner page.
400 / 422Zip refused.
type
must match this configuration. Path must be
{id}/specification/...
. Or
/commit
without a real
workspaceRunId
.
Unzip and check
specification/config.json
. Do not invent the workspace id.
415
/push
did not receive a zip. The endpoint consumes
multipart/form-data
part
file
.
POST the zip bytes. Do not JSON. Boundary must not start with
=
. With
requests
, use
files=
and do not also set
Content-Type
.
503Scanner or a proxy in front of it is down.Retry when the operator says the scanner is healthy.
JSON stdout must include
ok
,
truncated
, asset counts by type,
skipped
,
failures
, and
publish
with
uploaded
,
failed
,
completed
,
workspaceRunId
,
scanRunId
,
notes
.
Read configuration id from
--config
,
SCANNER_CONFIGURATION_ID
, then
SCANNER_CONFIG_ID
. One id. Zip
type
is the source constant
ASSET_TYPE
. A customer script that can emit more than one zip type is a generation failure.
每次失败都在 stderr 打印以下内容并以退出码 2 结束:
FAILED step=<name> http=<code>
where: <call>
request: <method and path, no secrets>
response fields: <names only>
why: <one sentence>
body: <response snippet with secrets removed>
next: <what to fix>
不要只打印
HTTP Error 503:
或 traceback。
httpwhynext
0 / connection refused无法连接该 Anypoint host。确认
--anypoint-base
/
ANYPOINT_BASE
可以访问。Token 和 push 都使用
{该 host}/agent-scanner
。
401 / 403Connected App 被拒绝。Secret 错误,或该组织缺少
manage:exchange
。
在与 client id 相同的 App 上重置 secret,并将其 scope 到该组织。
404Organization id、configuration id 或
/agent-scanner
path 在该 Anypoint host 上不正确。
使用
{ANYPOINT_BASE}/agent-scanner
,并从 Exchange scanner 页面复制两个 id。
400 / 422ZIP 被拒绝。
type
必须与此配置匹配。Path 必须为
{id}/specification/...
。或者
/commit
没有真实的
workspaceRunId
。
解压并检查
specification/config.json
。不要编造 workspace id。
415
/push
没有收到 ZIP。该 endpoint 接受名为
file
的
multipart/form-data
part。
POST ZIP 字节,不要使用 JSON。Boundary 不能以
=
开头。使用 requests 时采用
files=
,不要同时设置
Content-Type
。
503Scanner 或其前置 proxy 不可用。在运维人员确认 scanner 健康后重试。
JSON stdout 必须包含
ok
、
truncated
、按类型统计的资产数量、
skipped
、
failures
,以及
publish
;
publish
中包含
uploaded
、
failed
、
completed
、
workspaceRunId
、
scanRunId
、
notes
。
按
--config
、
SCANNER_CONFIGURATION_ID
、
SCANNER_CONFIG_ID
的顺序读取 configuration id,并且只能使用一个 id。ZIP 的
type
是源常量
ASSET_TYPE
。能够生成多种 ZIP type 的客户脚本属于生成失败。

Provider-agnostic UX, asset-type-specific pull

Provider-agnostic UX、asset-type-specific pull

The generated script is the laptop half of pull
execute
. Provider SDK calls and form fields change. Customer UX does not.
  • Provider-agnostic UX. Same flags, same “prompt only what is missing”, same numbered stderr, same FAILED block, same JSON stdout — AWS, Azure, GCP, Databricks, Snowflake, Kong, or a new provider. Only the pull-form labels and that bundle’s inventory calls change.
  • Language-agnostic I/O. Python, Bash, Node, Java, Go, PowerShell: same flag names, env names, step labels, JSON keys.
  • Asset-type-specific discovery. One source constant,
    ASSET_TYPE
    . Classify with the probe in that bundle’s inventory, the way pull Java does. Never by name. Never “every READY row from a shared list”.
Zipping
harness_model_Bedrock
as
type: mcp
, or zipping
agent_scanner_mcp_fixture
as
type: agent
, is a generation failure even when both runtimes appeared in
ListAgentRuntimes
.
生成的脚本是 pull
execute
的笔记本端。Provider SDK 调用和 form fields 会变化,但客户 UX 不变。
  • Provider-agnostic UX。 无论使用 AWS、Azure、GCP、Databricks、Snowflake、Kong 还是新 provider,都使用相同 flags、相同的“仅提示缺失项”、相同编号 stderr、相同 FAILED 块和相同 JSON stdout。只有 pull-form labels 和对应 bundle 的 inventory calls 发生变化。
  • Language-agnostic I/O。 Python、Bash、Node、Java、Go、PowerShell 使用相同 flag 名称、env 名称、step labels 和 JSON keys。
  • Asset-type-specific discovery。 唯一源常量是
    ASSET_TYPE
    。按照对应 bundle 清单中的 probe 进行分类,方式与 pull Java 相同。绝不能根据名称分类,也不能把共享 list 中的每个 READY row 都当作目标。
将
harness_model_Bedrock
作为
type: mcp
打包,或将
agent_scanner_mcp_fixture
作为
type: agent
打包,均属于生成失败,即使它们都出现在
ListAgentRuntimes
中。

Same job, any language

Same job, any language

Whatever they named (Python, Bash, Node, Java, Go, PowerShell, or another runtime) the generated file must parse in that language and do the same job: pull-form provider login, list one zip type, MuleSoft token,
POST .../push
, optional commit, FAILED block, JSON stdout. Do not emit Python because Bash is hard.
Run these on the generated file before claiming it works. If the checker cannot run here, search the file for the forbidden patterns.
They askedMust pass
Python
python3 -m py_compile FILE
. Search for
args.[a-z]+-
. Any match fails.
Node /
.mjs
node --check FILE
.
Bash
bash -n FILE
, then search for
}}}}
and
--region ${
. Any match fails.
Javaproject compile.
Go
go build
.
Otherthat project's syntax check.
Do not nest
${CLI_REGION:-${AWS_REGION:-${AWS_DEFAULT_REGION:-x}}}}
. Sequential assignments only:
bash
region=""
[ -n "${CLI_REGION:-}" ] && region="$CLI_REGION"
[ -z "$region" ] && region="${AWS_REGION:-}"
[ -z "$region" ] && region="${AWS_DEFAULT_REGION:-}"
region="$(unquote_aws "$region")"
Python: stdlib plus the cloud SDK already on the laptop; AWS uses
boto3
. Node: Node 18+
fetch
unless their project already has an SDK. Bash:
curl
,
jq
,
zip
; token call is form-urlencoded, never JSON content-type. Same env names (
ANYPOINT_BASE
,
SCANNER_CONFIGURATION_ID
,
ANYPOINT_CLIENT_SECRET
,
PUSH_COMMIT
).
无论用户指定 Python、Bash、Node、Java、Go、PowerShell 或其他 runtime,生成文件都必须能够按该语言解析,并完成相同工作:pull-form provider login、列出一种 ZIP type、MuleSoft token、
POST .../push
、可选 commit、FAILED 块和 JSON stdout。不要因为 Bash 难以实现就输出 Python。
在声明可用前,必须对生成文件运行以下检查。如果当前环境无法运行检查器,则搜索文件中的禁止模式。
用户指定语言必须通过
Python
python3 -m py_compile FILE
。搜索
args.[a-z]+-
,任何匹配都失败。
Node /
.mjs
node --check FILE
。
Bash
bash -n FILE
,然后搜索
}}}}
和
--region ${
。任何匹配都失败。
Java项目编译。
Go
go build
。
其他对应项目的语法检查。
不要嵌套
${CLI_REGION:-${AWS_REGION:-${AWS_DEFAULT_REGION:-x}}}}
。只能顺序赋值:
bash
region=""
[ -n "${CLI_REGION:-}" ] && region="$CLI_REGION"
[ -z "$region" ] && region="${AWS_REGION:-}"
[ -z "$region" ] && region="${AWS_DEFAULT_REGION:-}"
region="$(unquote_aws "$region")"
Python:stdlib,加上笔记本上已有的云 SDK;AWS 使用
boto3
。Node:Node 18+ 的
fetch
,除非项目已经使用其他 SDK。Bash:
curl
、
jq
、
zip
;token 调用使用 form-urlencoded,绝不能使用 JSON content-type。所有语言使用相同 env 名称(
ANYPOINT_BASE
、
SCANNER_CONFIGURATION_ID
、
ANYPOINT_CLIENT_SECRET
、
PUSH_COMMIT
)。

Catalog of calls

调用 catalog

Shape reminder only. The customer paste is their own OpenAPI, Postman collection, or redacted request and response. Do not embed a block from here because they named that provider. Use a block only when they pasted that same inventory. A provider that is not in this catalog is onboarded the same way: their inventory, their auth, their language, the same
POST .../push
, the same
POST .../commit
.
这里仅作为结构提示。客户应粘贴自己的 OpenAPI、Postman collection 或已脱敏的请求与响应。不要因为客户指定了 provider 就直接嵌入这里的代码块。只有当客户粘贴了同一份 inventory 时,才能使用这里的对应块。不在此 catalog 中的 provider 也采用相同方式:使用客户自己的 inventory、auth 和 language,并使用相同的
POST .../push
与
POST .../commit
。

AWS agents and MCP (AgentCore)

AWS agents 和 MCP(AgentCore)

Already logged in on this machine, or access keys. Service
bedrock-agentcore-control
. Call boto3
list_agent_runtimes
(CLI name
list-agent-runtimes
). Do not POST to the path
/ListAgentRuntimes
.
  • List:
    list-agent-runtimes
    ,
    max-results
    100, token
    next-token
    . Response array
    agentRuntimes
    . Stop after 50 pages. A stopped list is partial.
  • Keep runtimes whose
    status
    is
    READY
    .
  • External id is the runtime id. Display name is the runtime name.
  • This script publishes one asset type. Shared list is not shared publish.
  • Agent (
    ASSET_TYPE = "agent"
    ):
    get-agent-runtime
    before any A2A zip. Skip
    serverProtocol=MCP
    (count only unless
    --verbose
    ). Then
    bedrock-agentcore
    get-agent-card
    . If that returns a validation error that the card is only for A2A agents, build a card from the runtime id.
    url
    is
    https://bedrock-agentcore.{region}.amazonaws.com/runtimes/{id}/invocations
    .
    protocolVersion
    is
    0.3.0
    .
    description
    is required.
    version
    is
    1.0.0
    .
    capabilities
    is
    { "streaming": true }
    . Both mode arrays are
    ["text"]
    .
    skills
    is
    []
    . If GetAgentCard returns v1 interfaces and no
    url
    , write
    a2a-v1-card.json
    and keep
    supportedInterfaces
    .
  • MCP (
    ASSET_TYPE = "mcp"
    ): same list, then
    get-agent-runtime
    for
    agentRuntimeArn
    , then
    list-agent-runtime-endpoints
    for
    qualifier
    . SigV4 JSON-RPC
    initialize
    then
    tools/list
    to
    https://bedrock-agentcore.{region}.amazonaws.com/runtimes/{urlencoded ARN}/invocations?qualifier={endpointName}
    . Service is
    bedrock-agentcore
    . Null
    initialize
    result = not MCP; skip (count only;
    --verbose
    may print
    skipped {id} not MCP
    ). Name is never classification. Do not POST
    /runtimes/{id}/invocations/mcp
    . Exchange
    transport.path
    /mcp
    is the zip field only.
使用本机已登录状态,或 access keys。Service 为
bedrock-agentcore-control
。调用 boto3
list_agent_runtimes
(CLI 名称为
list-agent-runtimes
)。不要 POST 到
/ListAgentRuntimes
path。
  • List:
    list-agent-runtimes
    ,
    max-results
    为 100,token 为
    next-token
    。响应数组为
    agentRuntimes
    。最多读取 50 页。停止读取表示清单不完整。
  • 保留
    status
    为
    READY
    的 runtimes。
  • External id 是 runtime id。Display name 是 runtime name。
  • 本脚本只发布一种资产类型。 共享 list 不代表共享发布。
  • Agent(
    ASSET_TYPE = "agent"
    ):生成 A2A ZIP 前先执行
    get-agent-runtime
    。跳过
    serverProtocol=MCP
    (仅计数,除非使用
    --verbose
    ),然后调用
    bedrock-agentcore
    的
    get-agent-card
    。如果返回验证错误,说明 card 仅适用于 A2A agents,则根据 runtime id 合成 card。
    url
    为
    https://bedrock-agentcore.{region}.amazonaws.com/runtimes/{id}/invocations
    。
    protocolVersion
    为
    0.3.0
    。
    description
    必填。
    version
    为
    1.0.0
    。
    capabilities
    为
    { "streaming": true }
    。两个 mode 数组均为
    ["text"]
    。
    skills
    为
    []
    。如果 GetAgentCard 返回 v1 interfaces 且没有
    url
    ,则写入
    a2a-v1-card.json
    并保留
    supportedInterfaces
    。
  • MCP(
    ASSET_TYPE = "mcp"
    ):使用同一 list,然后通过
    get-agent-runtime
    获取
    agentRuntimeArn
    ,再通过
    list-agent-runtime-endpoints
    获取
    qualifier
    。向
    https://bedrock-agentcore.{region}.amazonaws.com/runtimes/{urlencoded ARN}/invocations?qualifier={endpointName}
    依次执行 SigV4 JSON-RPC
    initialize
    和
    tools/list
    。Service 为
    bedrock-agentcore
    。
    initialize
    result 为 null 表示不是 MCP,应跳过(仅计数;
    --verbose
    可打印
    skipped {id} not MCP
    )。名称绝不能作为分类依据。不要 POST
    /runtimes/{id}/invocations/mcp
    。Exchange
    transport.path
    /mcp
    只是 ZIP 字段。

AWS REST (API Gateway v1)

AWS REST(API Gateway v1)

  • List:
    aws apigateway get-rest-apis
    ,
    limit
    500, token query
    position
    .
  • Stages:
    get-stages
    for that
    rest-api-id
    . No stage means skip that API (count only unless
    --verbose
    ).
  • Export:
    get-export
    with
    export-type
    oas30
    and
    accepts
    application/json
    .
  • One asset per stage. External id is
    {apiId}__{stage}
    .
  • List:
    aws apigateway get-rest-apis
    ,
    limit
    为 500,查询 token 为
    position
    。
  • Stages:对对应
    rest-api-id
    调用
    get-stages
    。没有 stage 时跳过该 API(仅计数,除非使用
    --verbose
    )。
  • Export:调用
    get-export
    ,其中
    export-type
    为
    oas30
    ,
    accepts
    为
    application/json
    。
  • 每个 stage 对应一个资产。External id 为
    {apiId}__{stage}
    。

Azure AI Foundry agents

Azure AI Foundry agents

az
already logged in. List URL they must confirm:
https://{resource}.services.ai.azure.com/api/projects/{project}/agents?api-version=v1
. Detail:
GET
that host
/agents/{id}?api-version=v1
. Stop after 100 pages or 50 agents.
az
已经登录。需要用户确认 list URL:
https://{resource}.services.ai.azure.com/api/projects/{project}/agents?api-version=v1
。Detail:对该 host 执行
GET /agents/{id}?api-version=v1
。最多读取 100 页或 50 个 agents。

Azure API Management REST

Azure API Management REST

az
already logged in. List APIs with the API Management resource in the subscription, resource group, and service name they provide. Export each API as OpenAPI. Caps: 1000 instances, 10000 APIs.
az
已经登录。使用用户提供的 subscription、resource group 和 service name 列出 API Management resource 中的 API。将每个 API 导出为 OpenAPI。上限:1000 个实例,10000 个 API。

Azure API Management MCP

Azure API Management MCP

GET https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.ApiManagement/service?api-version=2025-09-01-preview
, then
GET .../service/{name}/apis?api-version=2025-09-01-preview
with
$filter=properties/type eq 'mcp'
. One MCP card per API.
GET https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.ApiManagement/service?api-version=2025-09-01-preview
,然后执行
GET .../service/{name}/apis?api-version=2025-09-01-preview
,并使用
$filter=properties/type eq 'mcp'
。每个 API 对应一个 MCP card。

Google Vertex agents

Google Vertex agents

gcloud
already logged in (ADC, scope
cloud-platform
). Same list API as pull
VertexAgentScannerService
. Prompt GCP Project ID and Location. Do not prompt Service Account Email or Private Key unless they pasted a service-account key as the auth they will actually use. Pull form is
ServiceAccountCredentials
from those fields; both mint a Bearer token for the same host.
GET https://{location}-aiplatform.googleapis.com/v1/projects/{project}/locations/{location}/reasoningEngines?pageSize=100
. Follow
pageToken
. Cap 10000. Connection test
pageSize=1
.
Zip directory (push external id) is
projectId + location + engineId
with no separators (
getAgentIdFromName
, example
test-projectus-central1123456789
). A Vertex zip named only the last path segment of
name
is a generation failure.
Card: look at
spec.classMethods
for
name
on_message_send
and
a2a_agent_card
. If that JSON is A2A v0.3 or v1, use it. Always set
url
to
https://{location}-aiplatform.googleapis.com/v1/{engine.name}:query
. If there is no card, write
a2a-card.json
with
name
/
description
from
displayName
and
description
(empty string if missing),
protocolVersion
0.3.0
,
version
1.0.0
,
capabilities
{ "streaming": false }
,
defaultInputModes
["text","json"]
,
defaultOutputModes
["json"]
,
skills
[]
.
gcloud
已经登录(ADC,scope 为
cloud-platform
)。List API 与 pull
VertexAgentScannerService
相同。提示 GCP Project ID 和 Location。除非用户粘贴了 service-account key 作为实际使用的认证方式,否则不要提示 Service Account Email 或 Private Key。Pull form 使用来自这些字段的
ServiceAccountCredentials
;两者都为同一 host 签发 Bearer token。
GET https://{location}-aiplatform.googleapis.com/v1/projects/{project}/locations/{location}/reasoningEngines?pageSize=100
。跟踪
pageToken
。上限为 10000。连接测试使用
pageSize=1
。
Push external id 对应的 ZIP 目录是
projectId + location + engineId
,不含分隔符(
getAgentIdFromName
,例如
test-projectus-central1123456789
)。仅使用
name
最后一个 path segment 作为 Vertex ZIP 名称属于生成失败。
Card:检查
spec.classMethods
中是否存在名称为
on_message_send
的
a2a_agent_card
。如果该 JSON 是 A2A v0.3 或 v1,则直接使用。无论如何,都将
url
设置为
https://{location}-aiplatform.googleapis.com/v1/{engine.name}:query
。如果没有 card,则写入
a2a-card.json
,其中
name
/
description
来自
displayName
和
description
(缺失时为空字符串),
protocolVersion
为
0.3.0
,
version
为
1.0.0
,
capabilities
为
{ "streaming": false }
,
defaultInputModes
为
["text","json"]
,
defaultOutputModes
为
["json"]
,
skills
为
[]
。

Google Apigee REST

Google Apigee REST

gcloud
already logged in (ADC). Prompt GCP Project ID (that value is the Apigee org in every path). Same calls as pull
ApigeeApiClient
. Do not prompt Service Account Email or Private Key unless they pasted a service-account key.
GET https://apigee.googleapis.com/v1/organizations/{project}/apis
, array
proxies
,
pageToken
, stop after 1000 pages. Then
GET .../apis/{api}/deployments
. Skip when
deployments
is missing or empty. Each deployment needs
environment
and
revision
. Download
GET .../apis/{api}/revisions/{rev}?format=bundle
. Take the first valid
openapi.yaml
or
openapi.json
under
apiproxy/resources/oas/
. One zip per proxy. If no bundle has OAS, synthesize
openapi
3.0.0
,
info.title
the proxy name,
info.version
current
,
paths
{}
,
servers
[{ "url": "https://{project}-{firstEnvironment}.apigee.net" }]
. External id
apigee-{proxyName}
.
gcloud
已经登录(ADC)。提示 GCP Project ID(该值就是所有 path 中的 Apigee org)。调用与 pull
ApigeeApiClient
相同。不要提示 Service Account Email 或 Private Key,除非用户粘贴了 service-account key。
GET https://apigee.googleapis.com/v1/organizations/{project}/apis
,数组为
proxies
,使用
pageToken
,最多读取 1000 页。然后执行
GET .../apis/{api}/deployments
。
deployments
缺失或为空时跳过。每个 deployment 都需要
environment
和
revision
。下载
GET .../apis/{api}/revisions/{rev}?format=bundle
。取
apiproxy/resources/oas/
下第一个有效的
openapi.yaml
或
openapi.json
。每个 proxy 对应一个 ZIP。如果 bundle 中没有 OAS,则合成
openapi
3.0.0
,其中
info.title
为 proxy name,
info.version
为
current
,
paths
为
{}
,
servers
为
[{ "url": "https://{project}-{firstEnvironment}.apigee.net" }]
。External id 为
apigee-{proxyName}
。

Google Cloud Run MCP (customer-supplied)

Google Cloud Run MCP(客户提供)

Not
VERTEX_MCP
. That enum has no pull class. Do not list reasoning engines.
gcloud
ADC. Prompt GCP Project ID and Location. List
GET https://run.googleapis.com/v2/projects/{project}/locations/{location}/services
with an access token. For each service
uri
, JSON-RPC
initialize
(
protocolVersion
2025-03-26
) then
tools/list
to
POST {uri}/
with an identity token (
gcloud auth print-identity-token --audiences={uri}
). Null
initialize
result = skip (count only unless
--verbose
). HTTP 401/403 on initialize is FAILED. Do not POST
https://run.googleapis.com/mcp-handshake
.
Zip
mcp-metadata.json
:
transport.kind
streamableHttp
,
transport.path
/
. If
capabilities
is present, four booleans
tools
,
resources
,
prompts
,
logging
. Omit
serverInfo
. External id is the service id (last segment of
name
).
这不是
VERTEX_MCP
。该枚举没有 pull class。不要列出 reasoning engines。
使用
gcloud
ADC。提示 GCP Project ID 和 Location。使用 access token 执行
GET https://run.googleapis.com/v2/projects/{project}/locations/{location}/services
。对每个 service
uri
,先执行 JSON-RPC
initialize
(
protocolVersion
2025-03-26
),再向
POST {uri}/
执行
tools/list
,并使用 identity token(
gcloud auth print-identity-token --audiences={uri}
)。
initialize
result 为 null 时跳过(仅计数,除非使用
--verbose
)。initialize 返回 HTTP 401/403 时为 FAILED。不要 POST
https://run.googleapis.com/mcp-handshake
。
ZIP 中的
mcp-metadata.json
:
transport.kind
为
streamableHttp
,
transport.path
为
/
。如果存在
capabilities
,则包含四个 boolean:
tools
、
resources
、
prompts
、
logging
。省略
serverInfo
。External id 是 service id,即
name
的最后一个 segment。

Databricks agents

Databricks agents

They give a workspace URL. List serving endpoints. Then
GET {workspace}/api/2.0/serving-endpoints/{name}/openapi
. Cap 10000. Reject a workspace URL that is not public https.
客户提供 workspace URL。列出 serving endpoints,然后执行
GET {workspace}/api/2.0/serving-endpoints/{name}/openapi
。上限为 10000。拒绝不是公开 https 的 workspace URL。

Databricks MCP

Databricks MCP

Same workspace login. Try, in order,
/api/2.0/mcp/functions/system/ai
,
/api/2.0/mcp/sql
,
/api/2.0/mcp/genie
,
/api/2.1/unity-catalog/connections
,
/api/2.0/unity-catalog/connections
,
/api/2.0/preview/apps
,
/api/2.0/apps
,
GET /api/2.0/genie/spaces
. A 404 on the first page means that source is absent.
使用同一 workspace 登录。依次尝试
/api/2.0/mcp/functions/system/ai
、
/api/2.0/mcp/sql
、
/api/2.0/mcp/genie
、
/api/2.1/unity-catalog/connections
、
/api/2.0/unity-catalog/connections
、
/api/2.0/preview/apps
、
/api/2.0/apps
、
GET /api/2.0/genie/spaces
。第一页返回 404 表示该 source 不存在。

Snowflake agents

Snowflake agents

They give an account URL. Header
Authorization: Bearer
and
X-Snowflake-Authorization-Token-Type: PROGRAMMATIC_ACCESS_TOKEN
. List databases, schemas, agents, then read
agent_spec
.
客户提供 account URL。使用
Authorization: Bearer
和
X-Snowflake-Authorization-Token-Type: PROGRAMMATIC_ACCESS_TOKEN
。依次列出 databases、schemas、agents,然后读取
agent_spec
。

Snowflake MCP

Snowflake MCP

POST {account}/api/v2/statements
with SQL
SHOW MCP SERVERS
. Then JSON-RPC
initialize
, then
tools/list
. A failed handshake is a skip (count only unless
--verbose
).
POST {account}/api/v2/statements
,SQL 为
SHOW MCP SERVERS
。然后执行 JSON-RPC
initialize
和
tools/list
。握手失败时跳过(仅计数,除非使用
--verbose
)。

Microsoft Copilot Studio agents

Microsoft Copilot Studio agents

GET https://api.powerplatform.com/environmentmanagement/environments?api-version=2024-10-01
. Then Dataverse
bots
with the published, non-msdyn filter. Dataverse host must look like
https://{name}.crm.dynamics.com
.
GET https://api.powerplatform.com/environmentmanagement/environments?api-version=2024-10-01
。然后查询 Dataverse
bots
,并应用 published、non-msdyn filter。Dataverse host 必须形如
https://{name}.crm.dynamics.com
。

Kong REST

Kong REST

Bearer token in the environment, not in the file. Control planes, then services, routes, plugins. OpenAPI body is
GET {host}/v3/apis/{id}/specifications/{specId}
. Do not invent an OpenAPI document from the route list.
Bearer token 放在环境中,不放在文件中。先列出 control planes,再列出 services、routes、plugins。OpenAPI body 为
GET {host}/v3/apis/{id}/specifications/{specId}
。不要根据 route list 自行创造 OpenAPI 文档。

GoDaddy agents

GoDaddy agents

GET {baseUrl}/v1/agents?protocol=A2A&limit=20&offset={offset}
. Cap 1000.
baseUrl
must be public https.
GET {baseUrl}/v1/agents?protocol=A2A&limit=20&offset={offset}
。上限为 1000。
baseUrl
必须是公开 https。

Claude agents

Claude agents

GET https://api.anthropic.com/v1/agents?limit=100&page={next_page}
. Headers
X-Api-Key
from the environment,
anthropic-version: 2023-06-01
,
anthropic-beta: managed-agents-2026-04-01
. Card
url
is
https://api.anthropic.com/v1/agents/{id}/messages
.
GET https://api.anthropic.com/v1/agents?limit=100&page={next_page}
。Headers 包含环境中的
X-Api-Key
、
anthropic-version: 2023-06-01
和
anthropic-beta: managed-agents-2026-04-01
。Card
url
为
https://api.anthropic.com/v1/agents/{id}/messages
。

LangSmith agents

LangSmith agents

GET {apiHost}/v2/deployments?status=READY&limit=100&offset=
. Then
POST {custom_url}/assistants/search
and
GET {custom_url}/.well-known/agent-card.json
.
GET {apiHost}/v2/deployments?status=READY&limit=100&offset=
。然后执行
POST {custom_url}/assistants/search
和
GET {custom_url}/.well-known/agent-card.json
。

Salesforce Agentforce

Salesforce Agentforce

GET {instance}/services/data/v64.0/query
. SOQL
SELECT Id, DeveloperName, MasterLabel FROM BotDefinition WHERE IsDeleted = false
. Follow
nextRecordsUrl
for at most 50 pages. External id is
Id
.
GET {instance}/services/data/v64.0/query
。SOQL 为
SELECT Id, DeveloperName, MasterLabel FROM BotDefinition WHERE IsDeleted = false
。最多跟踪
nextRecordsUrl
50 页。External id 为
Id
。

Bedrock agents (not AgentCore)

Bedrock agents(不是 AgentCore)

aws bedrock list-agents
, then
get-agent
, versions, aliases. A missing permission omits that field and the script continues. Do not mix this inventory with AgentCore
list-agent-runtimes
.
aws bedrock list-agents
,然后执行
get-agent
、versions 和 aliases。缺少权限导致某个字段缺失时,忽略该字段并继续。不要将此 inventory 与 AgentCore
list-agent-runtimes
混合。

ServiceNow agents

ServiceNow agents

Not a shipped pull scanner. Use it only if they confirm this list. Client credentials token, then
alm_ai_system_digital_asset
. Do not call
sn_aia_agent
. Ask them what to put in the card
url
.
这不是内置 pull scanner。只有用户确认此 list 时才能使用。使用 client credentials token,然后调用
alm_ai_system_digital_asset
。不要调用
sn_aia_agent
。询问用户应在 card
url
中填写什么。

No calls exist

不存在调用

Do not write a script for Azure AI Foundry MCP, Microsoft 365 Copilot, Vertex MCP, Gemini agents, or Gemini MCP from those enum names. There is no pull-scanner call to copy. Ask them for the list call, or stop. A customer-supplied Cloud Run MCP inventory is a list-plus-handshake they paste; that is not the Vertex MCP enum.
不要仅根据 Azure AI Foundry MCP、Microsoft 365 Copilot、Vertex MCP、Gemini agents 或 Gemini MCP 这些枚举名称编写脚本。没有可直接复制其内容的 pull-scanner call。要求用户提供 list call,或者停止。客户提供的 Cloud Run MCP inventory 是用户粘贴的 list 加握手,不属于 Vertex MCP 枚举。

ZIP and push

ZIP 与 push

One asset is one zip. The zip has one top-level directory. That directory name is the external id, at most 255 characters, the provider id, not the display name.
specification/config.json
:
json
{ "name": "<display name>", "type": "agent", "description": "<optional, max 500 chars>" }
type
is the baked
ASSET_TYPE
and must match that configuration.
Artifact JSON must pass the Exchange agent-fabric schemas (tag
1.2609.1
:
agent_card
,
agent_card_v1
,
other_card
,
mcp_metadata
). Do not invent a second subset.
A2A v0.3 (
a2a-card.json
) required keys:
name
,
description
,
protocolVersion
,
url
,
version
,
capabilities
,
defaultInputModes
(at least one),
defaultOutputModes
(at least one),
skills
. Synthesized AgentCore fallbacks use
protocolVersion
0.3.0
. Skill objects, when present, need
id
,
name
,
description
, and
tags
.
A2A v1 (
a2a-v1-card.json
):
supportedInterfaces
or
supported_interfaces
with a callable
url
; never a top-level
url
.
MCP (
mcp-metadata.json
):
transport
required; if emitting
capabilities
, emit all four booleans
tools
,
resources
,
prompts
,
logging
; omit
serverInfo
.
REST artifact is the exported OpenAPI document. It must contain
openapi
or
swagger
.
Push, to that one configuration id.
/push
is the zip.
http
POST {ANYPOINT_BASE}/agent-scanner/api/v1/organizations/{ANYPOINT_ORG_ID}/scanner-configurations/{configId}/push
Authorization: Bearer <token>
Content-Type: multipart/form-data; boundary=----pushcollector7b1c

------pushcollector7b1c
Content-Disposition: form-data; name="file"; filename="{externalId}.zip"
Content-Type: application/zip

<zip bytes>
------pushcollector7b1c--
Required Python (or the same bytes in the language they named). Copy the boundary; do not start it with
=
.
python
def _multipart_zip(filename, payload):
    boundary = "----pushcollector7b1c"
    head = (
        f"--{boundary}\r\n"
        f'Content-Disposition: form-data; name="file"; filename="{filename}"\r\n'
        "Content-Type: application/zip\r\n\r\n"
    ).encode()
    tail = f"\r\n--{boundary}--\r\n".encode()
    return head + payload + tail, f"multipart/form-data; boundary={boundary}"
requests
equivalent:
files={"file": (f"{external_id}.zip", zip_bytes, "application/zip")}
and do not set
Content-Type
yourself (that drops the boundary → 415).
curl
:
-F "file=@{externalId}.zip;type=application/zip"
. After writing, search the script for
json=
or
"Content-Type": "application/json"
on the
/push
URL. Any match is a generation failure. Search for
boundary================
or a boundary that starts with
=
. Any match is a generation failure.
HTTP 202 body has
workspaceRunId
. Read it. A generated script that calls
POST .../push-assets
is a generation failure.
  1. Finish with
    POST .../commit
    Content-Type: application/json
    {"workspaceRunId":"<id from 202>","complete":true|false}
    . The customer question is "Commit this scan? [y/N]". A generated script that calls
    POST .../complete
    or
    POST .../seal
    is a generation failure. A generated script that POSTs
    /commit
    when every
    /push
    failed, or with a homemade
    run-
    id, is a generation failure.
The zip must contain
{externalId}/specification/config.json
and
{externalId}/specification/<artifact>
.
{externalId}/config.json
at the top of the zip is invalid.
一个资产对应一个 ZIP。ZIP 有一个顶层目录。目录名是 external id,最多 255 个字符,必须使用 provider id,而不是 display name。
specification/config.json
:
json
{ "name": "<display name>", "type": "agent", "description": "<optional, max 500 chars>" }
type
是固定的
ASSET_TYPE
,并且必须与此配置匹配。
产物 JSON 必须通过 Exchange agent-fabric schemas(tag
1.2609.1
:
agent_card
、
agent_card_v1
、
other_card
、
mcp_metadata
)验证。不要自行创造第二个子集。
A2A v0.3(
a2a-card.json
)必填键:
name
、
description
、
protocolVersion
、
url
、
version
、
capabilities
、
defaultInputModes
(至少一个)、
defaultOutputModes
(至少一个)、
skills
。合成的 AgentCore fallback 使用
protocolVersion
0.3.0
。存在 skill objects 时,需要
id
、
name
、
description
和
tags
。
A2A v1(
a2a-v1-card.json
):
supportedInterfaces
或
supported_interfaces
中必须包含可调用的
url
;绝不能有顶层
url
。
MCP(
mcp-metadata.json
):
transport
必填;如果输出
capabilities
,则必须输出全部四个 boolean:
tools
、
resources
、
prompts
、
logging
;省略
serverInfo
。
REST 产物是导出的 OpenAPI 文档,其中必须包含
openapi
或
swagger
。
Push 到唯一的 configuration id。
/push
接收 ZIP。
http
POST {ANYPOINT_BASE}/agent-scanner/api/v1/organizations/{ANYPOINT_ORG_ID}/scanner-configurations/{configId}/push
Authorization: Bearer <token>
Content-Type: multipart/form-data; boundary=----pushcollector7b1c

------pushcollector7b1c
Content-Disposition: form-data; name="file"; filename="{externalId}.zip"
Content-Type: application/zip

<zip bytes>
------pushcollector7b1c--
Python 要求如下,或在用户指定语言中发送相同字节。复制该 boundary;不要让它以
=
开头。
python
def _multipart_zip(filename, payload):
    boundary = "----pushcollector7b1c"
    head = (
        f"--{boundary}\r\n"
        f'Content-Disposition: form-data; name="file"; filename="{filename}"\r\n'
        "Content-Type: application/zip\r\n\r\n"
    ).encode()
    tail = f"\r\n--{boundary}--\r\n".encode()
    return head + payload + tail, f"multipart/form-data; boundary={boundary}"
requests
等价写法:
files={"file": (f"{external_id}.zip", zip_bytes, "application/zip")}
,不要自行设置
Content-Type
,否则会丢失 boundary 并导致 415。
curl
:
-F "file=@{externalId}.zip;type=application/zip"
。写完后,在脚本中搜索
/push
URL 上的
json=
或
"Content-Type": "application/json"
。任何匹配都属于生成失败。搜索
boundary================
或以
=
开头的 boundary。任何匹配都属于生成失败。
HTTP 202 body 中包含
workspaceRunId
,必须读取。调用
POST .../push-assets
的脚本属于生成失败。
使用
POST .../commit
结束,
Content-Type: application/json
,请求体为
{"workspaceRunId":"<id from 202>","complete":true|false}
。面向客户的问题必须是
"Commit this scan? [y/N]"
。调用
POST .../complete
或
POST .../seal
的脚本属于生成失败。所有
/push
都失败时仍 POST
/commit
,或使用自行编造的
run-
id,均属于生成失败。
ZIP 必须包含
{externalId}/specification/config.json
和
{externalId}/specification/<artifact>
。ZIP 顶层的
{externalId}/config.json
无效。

Best Practices

最佳实践

  • One question per turn. ✅ the quoted sentences in Workflow. ❌ combining asset type, inventory, auth, or language in one reply.
  • Infer the provider; never ask its name. ✅ read the attached spec. ❌ "which provider?". On an invalid spec, ask for the missing list, fetch, handshake, export, or auth piece.
  • Mapping gate. ✅ show the mapping, then wait for "Does this look fine?". ❌ writing files in the mapping turn. ❌ treating a script dump as the mapping.
  • Quiet skips. ✅
    listed N, matching M, skipped K
    plus matching asset lines. ❌ skip ids,
    skipping MCP
    , or
    not MCP
    unless
    --verbose
    .
  • Omission is not deletion. ✅
    DELETE .../push/{externalId}
    only when they ask to unstage. ❌ DELETE because a second run's list is shorter.
  • Baked asset type. ✅
    ASSET_TYPE
    constant. ❌
    --asset-type
    or an environment variable that switches type.
  • 每轮只问一个问题。 ✅ 使用 Workflow 中加引号的句子。❌ 在一次回复中合并询问资产类型、清单、认证或语言。
  • 推断 provider;绝不询问名称。 ✅ 阅读附加规范。❌ 询问“which provider?”。规范无效时,询问缺少的 list、fetch、handshake、export 或 auth 部分。
  • Mapping gate。 ✅ 展示 mapping,然后等待
    "Does this look fine?"
    。❌ 在 mapping 轮次写文件。❌ 将脚本输出视为已经展示 mapping。
  • 安静地跳过。 ✅ 输出
    listed N, matching M, skipped K
    和匹配资产行。❌ 除非使用
    --verbose
    ,否则输出 skip ids、
    skipping MCP
    或
    not MCP
    。
  • 遗漏不是删除。 ✅ 只有用户要求取消暂存时才调用
    DELETE .../push/{externalId}
    。❌ 因为第二次运行的 list 更短就执行 DELETE。
  • 固定资产类型。 ✅ 使用
    ASSET_TYPE
    常量。❌ 使用
    --asset-type
    或用于切换类型的环境变量。

Troubleshooting

故障排查

HTTP 415 on POST /push: the body was not a ZIP as multipart part
file
. JSON,
json=
,
Content-Type: application/json
, a missing boundary, or a boundary that starts with
=
all produce 415. Use the
_multipart_zip
helper (or
files={"file": (...)}
without setting Content-Type).
No inventory file in this skill: this package does not ship provider OpenAPI files. If they ask which file to open, ask them to paste or attach their own specification.
Invalid or incomplete spec: do not invent calls and do not ask which provider. Ask for the missing list, fetch, handshake, export, or auth piece using the questions in Workflow.
Salesforce C2C or managed authorization-code login: that pull form is not customer-executable. Ask for a request and response they can run from their machine before writing files.
Zero matching assets: print
No matching {ASSET_TYPE} assets found.
, print JSON, exit 0. Do not call /push or /commit.
HTTP 401/403 on /push or /commit: Connected App missing
manage:exchange
, wrong organization, or the configuration is not a self-managed scanner they can write.
POST /push 返回 HTTP 415: 请求体不是名为
file
的 ZIP multipart part。JSON、
json=
、
Content-Type: application/json
、缺少 boundary,或 boundary 以
=
开头,都会产生 415。使用
_multipart_zip
helper,或在 requests 中使用
files={"file": (...)}
且不设置 Content-Type。
此 Skill 中没有 inventory 文件: 本软件包不提供 provider OpenAPI 文件。如果用户询问应打开哪个文件,要求其粘贴或附加自己的规范。
规范无效或不完整: 不要编造调用,也不要询问 provider 名称。使用 Workflow 中的问题,询问缺少的 list、fetch、handshake、export 或 auth 部分。
Salesforce C2C 或托管 authorization-code 登录: 该 pull form 无法由客户直接执行。编写文件前,要求用户提供可从其机器运行的请求和响应。
零匹配资产: 打印
No matching {ASSET_TYPE} assets found.
,打印 JSON,然后退出码 0。不要调用
/push
或
/commit
。
/push
或
/commit
返回 HTTP 401/403:
Connected App 缺少
manage:exchange
、组织错误,或者该配置不是可写入的自托管 scanner。

Related Skills

相关 Skills

  • skill setup-service-scanner: Create a pull scanner configuration that discovers assets from a connected cloud platform.
  • skill run-service-scan-and-view-results: Run a hosted scan and review discovered staging assets.
  • skill setup-service-scanner:创建用于从已连接云平台发现资产的 pull scanner 配置。
  • skill run-service-scan-and-view-results:运行托管扫描并检查已发现的暂存资产。