Vulnify

io.vulnifyv0.1.2更新于 Oct 10, 2026

Ask Vulnify before an AI agent acts. Check, record, and read policy decisions.

已验证Streamable HTTP可网页运行Developer ToolsSecurity & Monitoring

概览

AI 生成的概览

让助手在读取、写入、删除、导出或发送数据之前,先向 Vulnify 请求授权决定。

功能
Vulnify 是面向 AI 代理的运行时授权层:代理先询问,服务器返回 finalDecision,取值为 ALLOW、REVIEW 或 BLOCK。工具包括 check_action(不记录任何内容的试运行)、decide_action(记录真实安全事件和审计条目)、get_decision(读取决定,可选等待 REVIEW 最多 30 秒)、list_policies、test_policies(最多 200 个用例)、plan_policy_changes(始终为试运行并返回差异),以及 check_mcp_tool_call(把工具名映射为动作并记录决定,但不执行该工具)。
适用场景
当代理在操作数据前需要受策略约束,或需要为审计记录决定时使用。适合已使用 Vulnify 策略的团队,或希望加入由人工处理 REVIEW 的审核环节的场景。
运行要求
可使用托管端点 mcp.vulnify.io/mcp 并通过 Vulnify 登录(OAuth)或在请求头中发送 API 密钥,也可在 Node.js 20 或更高版本上用 npx 运行本地 npm 包 @vulnify/mcp。stdio 进程需要 VULNIFY_API_KEY;VULNIFY_BASE_URL 可选,默认指向 Vulnify API。每次工具调用都需要访问 Vulnify API 的网络连接。
安装前请注意
decide_action 和 check_mcp_tool_call 会写入安全事件和审计条目。plan_policy_changes 需要组织范围的 live 密钥,且仅为试运行;服务器无法批准或拒绝 REVIEW、保存策略或执行工具。VULNIFY_API_KEY 是机密,不要放入工具参数或已提交的配置文件,手动配置时优先使用测试密钥。用于敏感数据扫描的文本会转发给 Vulnify API,API 密钥的 IP 允许列表看到的是托管服务器的出口 IP,而不是用户的 IP。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Vulnify,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Web executable,通过 Streamable HTTP。 远程服务在工作区中配置后即可从网页运行时运行。

其他 MCP 客户端

把它添加到你客户端的 mcpServers 配置中。

{
  "mcpServers": {
    "mcp": {
      "type": "http",
      "url": "https://mcp.vulnify.io/mcp"
    }
  }
}

README

[Vulnify]

Vulnify MCP

Ask Vulnify before an AI agent reads, writes, deletes, exports, or sends data.
finalDecision is the authoritative result: ALLOW, REVIEW, or BLOCK.

[npm version] [npm downloads] [license] [CI]

Docs  ·  MCP  ·  Changelog  ·  Node SDK

[Every agent action gets a decision. ALLOW, REVIEW, or BLOCK.]

@vulnify/mcp is the MCP server for Vulnify, a runtime authorization layer for AI agents. The agent asks first. This process proxies https://api.vulnify.io. It does not store events or API keys.

Two transports, one server:

check_action is a dry run. It skips the PII scan and records nothing. decide_action records a real decision. A REVIEW waits for a person. This server cannot approve or deny one.

Application code that should decide inside your own process uses the Node SDK (@vulnify/sdk). This package does not depend on the SDK. The SDK turns some transport failures into a fail-closed decision. This server returns those failures as MCP tool errors, so a model does not read them as ALLOW.

Quickstart

The hosted guide is docs.vulnify.io/mcp. Client snippets for Cursor, Claude Code, Claude Desktop, and VS Code are in docs/clients.md.

Hosted server

https://mcp.vulnify.io/mcp keeps no session. Sign in with Vulnify.

Claude custom connector: add https://mcp.vulnify.io/mcp. Claude follows the 401 challenge, opens Vulnify sign-in, and stops on the consent page until you allow access. The steps are in docs/clients.md.

Cursor: Install Vulnify.

An OAuth session lists check_action, decide_action, get_decision, list_policies, and test_policies.

API key

A manual config can still send an API key on every request. Use a dedicated TEST key (vln_test_...). This works for Cursor, Claude Code, VS Code, and any client that can set a header:

json
{  "mcpServers": {    "vulnify": {      "url": "https://mcp.vulnify.io/mcp",      "headers": {        "Authorization": "Bearer ${env:VULNIFY_API_KEY}"      }    }  }}

X-Vulnify-Key: <key> is accepted for vln_live_... and vln_test_... keys. A request with no credentials gets 401 and:

WWW-Authenticate: Bearer realm="https://mcp.vulnify.io/mcp", resource_metadata="https://mcp.vulnify.io/.well-known/oauth-protected-resource/mcp", scope="decisions:read decisions:write policies:read policies:test"

GET /health does not require a key. GET /.well-known/oauth-protected-resource and GET /.well-known/oauth-protected-resource/mcp return the protected-resource document (resource https://mcp.vulnify.io/mcp, authorization server https://api.vulnify.io, the four scopes above, bearer header). Responses are JSON.

A vln_oat_... access token is checked with POST /oauth/introspect, then sent to /v1/mcp/*. check_action and test_policies need policies:test. decide_action needs decisions:write. get_decision needs decisions:read. list_policies needs policies:read. plan_policy_changes and check_mcp_tool_call stay on API-key and stdio sessions: an OAuth tools/list does not include them, because the API has no /v1/mcp route for policy apply or the MCP gateway. There is no approve tool and no deny tool.

A vln_ort_... refresh token, a vln_oac_... credential, or any other unrecognized secret receives 401 and WWW-Authenticate with error="invalid_token". A vln_live_... or vln_test_... key is checked with GET /v1/policies before initialize and tools/list. A key the API rejects receives that same 401. A successful check is reused for at most 60 seconds. The cache key is a hash of the API key.

Local stdio

Node.js 20 or newer.

bash
npx -y @vulnify/mcp

Cursor (.cursor/mcp.json):

json
{  "mcpServers": {    "vulnify": {      "command": "npx",      "args": ["-y", "@vulnify/mcp"],      "env": {        "VULNIFY_API_KEY": "${env:VULNIFY_API_KEY}"      }    }  }}

How it works

[An agent action goes to Vulnify. finalDecision is ALLOW (the action may run), REVIEW (a person decides), or BLOCK (the action does not run).]

The finalDecision field is the authoritative result. A tool error is not an ALLOW.

Tools

Every tool has a title and readOnlyHint, destructiveHint, idempotentHint, and openWorldHint. Hints tell the client how to present the tool. They do not change what the tool does.

ToolAPIRecords?readOnlyHintNotes
check_actionPOST /v1/policies/test (one case)NotrueSkips the PII scan and records nothing. No event id.
decide_actionPOST /v1/eventsYesfalseWrites a security event and an audit entry. finalDecision is the authoritative result.
get_decisionGET /v1/events/{id}NotrueReads a decision. Optional wait polls a REVIEW until ALLOW or BLOCK (30 seconds max).
list_policiesGET /v1/policiesNotruePolicies as code, sorted by name.
test_policiesPOST /v1/policies/testNotrueUp to 200 cases. Skips the PII scan. Proposed policies are not saved.
plan_policy_changesPOST /v1/policies/applyNotruedryRun is forced to true. Needs an org-wide LIVE key.
check_mcp_tool_callPOST /v1/gateway/mcpYesfalseMaps a tool name to an action and records the decision. Does not run the tool.

destructiveHint is false on every tool. openWorldHint is false on every tool, because each call stays inside the caller's own Vulnify organization. idempotentHint is true for the read-only tools and false for decide_action and check_mcp_tool_call. An idempotencyKey makes a retry of a recorded decision return the same event.

Policy list, test, and plan calls are limited to 60 requests per minute per key. Batch dry runs with test_policies. POST /v1/events has its own limit. The OpenAPI text says only that the limit was exceeded.

Safety

This server cannot change a review and cannot save a policy.

  • There is no approve tool and no deny tool. A human resolves a REVIEW in Vulnify.
  • There is no apply tool. plan_policy_changes calls POST /v1/policies/apply with dryRun: true on every request. The tool input has no dryRun field. The server sets dryRun last, so a caller cannot turn the dry run off. The tool returns the diff.
  • POST /v1/gateway/http is not a tool. On ALLOW, that API endpoint forwards the HTTP call. This server does not.

plan_policy_changes needs an org-wide LIVE key. A TEST key or an agent-bound key gets 403. An OAuth session does not list plan_policy_changes or check_mcp_tool_call.

OAuth scopes

User login is the hosted HTTP server. The local stdio process still uses an API key. The hosted server maps tools to scopes:

ToolScopeOAuth route
check_actionpolicies:testPOST /v1/mcp/policies/test
test_policiespolicies:testPOST /v1/mcp/policies/test
decide_actiondecisions:writePOST /v1/mcp/events
get_decisiondecisions:readGET /v1/mcp/events/{id}
list_policiespolicies:readGET /v1/mcp/policies
plan_policy_changesAPI key and stdio onlyOmitted from OAuth tools/list
check_mcp_tool_callAPI key and stdio onlyOmitted from OAuth tools/list

A token that is missing the scope gets a tool error that names the scope. That error is not an ALLOW. Active introspection results are reused for at most 60 seconds, and never past exp.

Distinct from the MCP gateway

https://mcp.vulnify.io/mcp (and the local stdio process) is the server an MCP client connects to. The client then calls the tools above.

check_mcp_tool_call is different. It sends one tool call to POST /v1/gateway/mcp on api.vulnify.io, records the decision, and stops. It does not execute the tool, and connecting a client to this server does not call that gateway.

IP allowlists

API-key IP allowlists are checked against the hosted server's egress IP when using https://mcp.vulnify.io/mcp, not the end user's IP. The hosted process calls api.vulnify.io from its own address. Users who need an IP allowlist should run the local npx/stdio mode (npx -y @vulnify/mcp). stdio runs on the user's machine, so the allowlist sees that machine.

Product

The screenshot is from a demo workspace. The agent is SupportBot.

[An allowed read: SupportBot, one record, internal destination, low risk.]

Audit exports in the Vulnify app are a JSON or CSV download that includes a SHA-256 checksum. SIEM export is JSON or CEF lines.

Configuration

VariableWhereRequiredPurpose
VULNIFY_API_KEYstdio processyesAPI key (vln_live_... or vln_test_...). HTTP does not fall back to this variable.
VULNIFY_BASE_URLbothnoAPI base URL. Default https://api.vulnify.io.
OAUTH_INTROSPECTION_SECRETHTTPfor user loginBearer secret for POST /oauth/introspect. Stays on the server. API keys work without it.
OPENAI_APPS_CHALLENGEHTTPnoWhen set, GET /.well-known/openai-apps-challenge returns this value as text/plain. Unset, that path is 404.
PORTHTTPnoListen port. Default 8080.
HOSTHTTPnoBind address. Default 0.0.0.0.

Use an agent-bound LIVE key when a recorded decision should count for one agent. plan_policy_changes needs an org-wide LIVE key.

VULNIFY_TEST_API_KEY is only for npm run test:live. The server does not read it.

HTTP server

bash
npx -y @vulnify/mcp --http

The container runs the HTTP server as a non-root user:

bash
docker build -t vulnify-mcp .docker run --rm -p 8080:8080 -e PORT=8080 vulnify-mcp

No API key is required to start the container. Send the key on each request.

bash
curl -sS localhost:8080/healthcurl -sS -o /dev/null -w '%{http_code}\n' -X POST localhost:8080/mcp \  -H 'content-type: application/json' -d '{}'

The health check prints JSON. The POST without a key prints 401.

GET /.well-known/mcp/server-card.json does not require a key. It lists the tools the server registers (names, descriptions, and input schemas), states that you can sign in with OAuth or send a Vulnify API key in a header, and links to the docs and this repository.

bash
curl -sS https://mcp.vulnify.io/.well-known/mcp/server-card.json

Errors

Tool failures are MCP tool errors (isError). The API key is not included.

StatusMeaning
401The API key or access token is missing, invalid, revoked, or expired.
403The key is bound to another agent, the caller IP is not allowlisted, the access token lacks a scope, or plan_policy_changes was called without an org-wide LIVE key.
413The JSON body is over the API's 200 KB limit.
429The key is rate limited. Policy calls are 60 per minute. Retry a recorded decision with the same idempotencyKey.

Security

Report a vulnerability to [email protected]. The disclosure policy is at vulnify.io/disclosure. See SECURITY.md.

Keys are not logged. Request logs are method, path, and status. content sent for a sensitive-data scan is forwarded to the API and is not written to this server's logs. The API scans that text in memory and does not store it.

This package does not run a shell and does not register hooks. Do not put a key in a tool argument or in a committed config file.

Network endpoints this process uses:

  • https://api.vulnify.io (or VULNIFY_BASE_URL) for every tool call, and for GET /v1/policies when an API key is checked. An API key is sent as Authorization: Bearer to /v1/*. A user access token is sent as Authorization: Bearer to /v1/mcp/*.
  • POST /oauth/introspect on that same origin, with Authorization: Bearer set to OAUTH_INTROSPECTION_SECRET, to validate vln_oat_... tokens. The secret is not sent to clients and is not logged.
  • https://mcp.vulnify.io/mcp is the hosted HTTP transport. The server process does not call that URL.

Development

bash
npm installnpm testnpm run lintnpm run build

npm run test:live calls list_policies on https://api.vulnify.io when VULNIFY_TEST_API_KEY is set, and skips when it is not. It does not record an event.

Publishing is described in RELEASING.md.

License

MIT. Copyright 2026 Vulnify.

来源:README.md,提交 cf0e0ac

工具

0
工具元数据尚未被收录。

版本历史

1
  1. v0.1.2最新Oct 10, 2026