PageSourceSearch

https://docs.controlzero.ai/assets/js/f1285d9a.c7408791.js

js controlzero.ai collected 2026-10-05 13:53:18 UTC 14,158 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkcontrolzero_docs||=[]).push([[407],{82002(e,n,r){r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>t,default:()=>h,frontMatter:()=>i,metadata:()=>o,toc:()=>d});const o=JSON.parse('{"id":"integrations/mcp","title":"MCP (Model Context Protocol)","description":"Wrap MCP calls with the SDK for deterministic enforcement, or offer cooperative policy checks to MCP clients.","source":"@site/docs/integrations/mcp.md","sourceDirName":"integrations","slug":"/integrations/mcp","permalink":"/docs/integrations/mcp","draft":false,"unlisted":false,"tags":[],"version":"current","sidebarPosition":8,"frontMatter":{"sidebar_position":8,"title":"MCP (Model Context Protocol)"},"sidebar":"docsSidebar","previous":{"title":"Kiro (AWS)","permalink":"/docs/integrations/kiro"},"next":{"title":"MCP Guard","permalink":"/docs/integrations/mcp-guard"}}');var s=r(74848),l=r(28453);const i={sidebar_position:8,title:"MCP (Model Context Protocol)"},t="MCP Integration",c={},d=[{value:"Overview",id:"overview",level:2},{value:"How It Works",id:"how-it-works",level:2},{value:"MCP Server Setup",id:"mcp-server-setup",level:2},{value:"Installation",id:"installation",level:3},{value:"Environment Variables",id:"environment-variables",level:3},{value:"Client Configuration",id:"client-configuration",level:2},{value:"Claude Code",id:"claude-code",level:3},{value:"Claude Desktop",id:"claude-desktop",level:3},{value:"Cline",id:"cline",level:3},{value:"Cursor",id:"cursor",level:3},{value:"Windsurf",id:"windsurf",level:3},{value:"SDK Integration",id:"sdk-integration",level:2},{value:"Python",id:"python",level:3},{value:"Node.js",id:"nodejs",level:3},{value:"Example Policy",id:"example-policy",level:2},{value:"MCP Resource URI Format",id:"mcp-resource-uri-format",level:2},{value:"Next Steps",id:"next-steps",level:2}];function a(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,l.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"mcp-integration",children:"MCP Integration"})}),"\n",(0,s.jsx)(n.p,{children:"Wrap MCP calls with the SDK for deterministic enforcement, or offer cooperative policy checks to MCP clients."}),"\n",(0,s.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,s.jsxs)(n.p,{children:["The Model Context Protocol (MCP) is an open standard for connecting AI models to external tools and data sources. Control Zero is built with MCP as a first-class integration point. An SDK wrapper using an enforcing ",(0,s.jsx)(n.code,{children:"guard()"})," call blocks a denied MCP tool call before it executes. MCP Guard exposes the same decision as a cooperative check when application code cannot host the SDK."]}),"\n",(0,s.jsx)(n.p,{children:"This integration covers all tools that support MCP servers, including:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Claude Code"})," (Anthropic's CLI coding tool)"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Cline"})," (VS Code AI coding extension)"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Cursor"})," (AI-powered IDE)"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Windsurf"})," (AI-powered IDE by Codeium)"]}),"\n",(0,s.jsx)(n.li,{children:(0,s.jsx)(n.strong,{children:"Any MCP-compatible client"})}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"how-it-works",children:"How It Works"}),"\n",(0,s.jsxs)(n.p,{children:["Control Zero uses the ",(0,s.jsx)(n.code,{children:"mcp.tool.call"})," action and ",(0,s.jsx)(n.code,{children:"mcp://{server}/{tool}"})," resource URIs. When application code calls ",(0,s.jsx)(n.code,{children:"guard(..., raise_on_deny=True)"}),", a deny raises ",(0,s.jsx)(n.code,{children:"PolicyDeniedError"})," before tool execution. MCP Guard returns the decision to the client and remains cooperative."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"Agent -> MCP Tool Call -> Control Zero Policy Check -> Tool Execution\n                              |\n                              v (if denied)\n                         PolicyDeniedError\n"})}),"\n",(0,s.jsx)(n.h2,{id:"mcp-server-setup",children:"MCP Server Setup"}),"\n",(0,s.jsxs)(n.p,{children:["The Control Zero MCP server is published to the Control Zero npm registry as ",(0,s.jsx)(n.code,{children:"@controlzero/mcp-server"})," and uses stdio transport. It carries the management tools and the cooperative ",(0,s.jsx)(n.code,{children:"check"})," tool; see ",(0,s.jsx)(n.a,{href:"/docs/guides/mcp-server",children:"MCP Server"})," for the tool list and ",(0,s.jsx)(n.a,{href:"/docs/integrations/mcp-guard",children:"MCP Cooperative Guard"})," for ",(0,s.jsx)(n.code,{children:"check"}),"."]}),"\n",(0,s.jsx)(n.h3,{id:"installation",children:"Installation"}),"\n",(0,s.jsxs)(n.p,{children:["Configure the Control Zero registry once: add ",(0,s.jsx)(n.code,{children:"@controlzero:registry=https://npm.controlzero.ai"})," to your ",(0,s.jsx)(n.code,{children:".npmrc"})," (or run ",(0,s.jsx)(n.code,{children:"npm config set @controlzero:registry https://npm.controlzero.ai"}),"). It applies to npm install and npx for the whole @controlzero scope."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"# Install globally\nnpm install -g @controlzero/mcp-server\n\n# Or run directly without installing:\nnpx -p @controlzero/mcp-server controlzero-mcp\n"})}),"\n",(0,s.jsx)(n.h3,{id:"environment-variables",children:"Environment Variables"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Variable"}),(0,s.jsx)(n.th,{children:"Required"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"CONTROLZERO_MGMT_KEY"})}),(0,s.jsx)(n.td,{children:"For management tools"}),(0,s.jsxs)(n.td,{children:["Management key (",(0,s.jsx)(n.code,{children:"cz_mgmt_*"}),")"]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"CONTROLZERO_API_KEY"})}),(0,s.jsxs)(n.td,{children:["For ",(0,s.jsx)(n.code,{children:"check"})]}),(0,s.jsxs)(n.td,{children:["Enforcement key (",(0,s.jsx)(n.code,{children:"cz_live_*"})," or ",(0,s.jsx)(n.code,{children:"cz_test_*"}),") for the project"]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.code,{children:"CONTROLZERO_API_URL"})}),(0,s.jsx)(n.td,{children:"No"}),(0,s.jsxs)(n.td,{children:["API base URL, default ",(0,s.jsx)(n.code,{children:"https://api.controlzero.ai"})]})]})]})]}),"\n",(0,s.jsx)(n.p,{children:"Set whichever keys the tools you use need. The examples below set both."}),"\n",(0,s.jsx)(n.h2,{id:"client-configuration",children:"Client Configuration"}),"\n",(0,s.jsx)(n.p,{children:"All clients launch the MCP server as a local stdio process."}),"\n",(0,s.jsx)(n.h3,{id:"claude-code",children:"Claude Code"}),"\n",(0,s.jsxs)(n.p,{children:["Add to ",(0,s.jsx)(n.code,{children:".claude/settings.json"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n  "mcpServers": {\n    "controlzero": {\n      "command": "controlzero-mcp",\n      "env": {\n        "CONTROLZERO_MGMT_KEY": "cz_mgmt_your_key_here",\n        "CONTROLZERO_API_KEY": "cz_live_your_api_key_here"\n      }\n    }\n  }\n}\n'})}),"\n",(0,s.jsx)(n.h3,{id:"claude-desktop",children:"Claude Desktop"}),"\n",(0,s.jsxs)(n.p,{children:["Add to ",(0,s.jsx)(n.code,{children:"claude_desktop_config.json"}),":"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n  "mcpServers": {\n    "controlzero": {\n      "command": "controlzero-mcp",\n      "env": {\n        "CONTROLZERO_MGMT_KEY": "cz_mgmt_your_key_here",\n        "CONTROLZERO_API_KEY": "cz_live_your_api_key_here"\n      }\n    }\n  }\n}\n'})}),"\n",(0,s.jsx)(n.h3,{id:"cline",children:"Cline"}),"\n",(0,s.jsx)(n.p,{children:"Add the Control Zero MCP server through the Cline settings panel in VS Code:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Open Cline settings."}),"\n",(0,s.jsx)(n.li,{children:"Navigate to the MCP Servers section."}),"\n",(0,s.jsxs)(n.li,{children:["Add a new stdio server with command: ",(0,s.jsx)(n.code,{children:"controlzero-mcp"})," and set ",(0,s.jsx)(n.code,{children:"CONTROLZERO_MGMT_KEY"})," and/or ",(0,s.jsx)(n.code,{children:"CONTROLZERO_API_KEY"})," in the environment."]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"cursor",children:"Cursor"}
1),"\n",(0,s.jsx)(n.p,{children:"Configure MCP servers in Cursor settings:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Open Cursor settings (Cmd/Ctrl + ,)."}),"\n",(0,s.jsx)(n.li,{children:'Search for "MCP" in the settings.'}),"\n",(0,s.jsxs)(n.li,{children:["Add a new stdio server with command ",(0,s.jsx)(n.code,{children:"controlzero-mcp"})," and environment variables ",(0,s.jsx)(n.code,{children:"CONTROLZERO_MGMT_KEY"})," and/or ",(0,s.jsx)(n.code,{children:"CONTROLZERO_API_KEY"}),"."]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"windsurf",children:"Windsurf"}),"\n",(0,s.jsx)(n.p,{children:"Windsurf supports MCP servers through its configuration:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Open Windsurf settings."}),"\n",(0,s.jsxs)(n.li,{children:["Add the Control Zero MCP server with command ",(0,s.jsx)(n.code,{children:"controlzero-mcp"})," and set ",(0,s.jsx)(n.code,{children:"CONTROLZERO_MGMT_KEY"})," and/or ",(0,s.jsx)(n.code,{children:"CONTROLZERO_API_KEY"})," in the environment."]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"sdk-integration",children:"SDK Integration"}),"\n",(0,s.jsx)(n.h3,{id:"python",children:"Python"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:'from controlzero import Client\n\ncz = Client(api_key="cz_live_your_api_key_here")\n\nasync def call_mcp_tool(server: str, tool: str, arguments: dict) -> dict:\n    """Call an MCP tool with policy enforcement."""\n\n    # Enforce the policy before calling the tool\n    cz.guard(\n        f"{server}/{tool}",\n        args={"agent_id": "coding-agent", "arguments": str(arguments)},\n        raise_on_deny=True,\n    )\n\n    # Policy check passed. Call the tool\n    return await mcp_client.callTool(server, tool, arguments)\n'})}),"\n",(0,s.jsx)(n.h3,{id:"nodejs",children:"Node.js"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-typescript",children:"function callMCPTool(server: string, tool: string, args: Record<string, any>) {\n  cz.guard(server, { method: tool, args, raiseOnDeny: true });\n\n  return mcpClient.callTool(server, tool, args);\n}\n"})}),"\n",(0,s.jsx)(n.h2,{id:"example-policy",children:"Example Policy"}),"\n",(0,s.jsx)(n.p,{children:"Control which MCP tools agents can use:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n  "name": "mcp-tool-governance",\n  "rules": [\n    {\n      "effect": "allow",\n      "action": "mcp.tool.call",\n      "resource": "mcp://filesystem/read_file"\n    },\n    {\n      "effect": "allow",\n      "action": "mcp.tool.call",\n      "resource": "mcp://filesystem/list_directory"\n    },\n    {\n      "effect": "deny",\n      "action": "mcp.tool.call",\n      "resource": "mcp://filesystem/write_file"\n    },\n    {\n      "effect": "deny",\n      "action": "mcp.tool.call",\n      "resource": "mcp://shell/execute"\n    },\n    {\n      "effect": "allow",\n      "action": "mcp.tool.call",\n      "resource": "mcp://database/read_query"\n    },\n    {\n      "effect": "deny",\n      "action": "mcp.tool.call",\n      "resource": "mcp://database/write_query"\n    }\n  ]\n}\n'})}),"\n",(0,s.jsx)(n.p,{children:"When applied by the SDK wrapper shown above, this policy allows agents to read files and query databases, but blocks file writes and shell execution."}),"\n",(0,s.jsx)(n.h2,{id:"mcp-resource-uri-format",children:"MCP Resource URI Format"}),"\n",(0,s.jsx)(n.p,{children:"Control Zero uses a consistent URI format for MCP resources:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"mcp://{server_name}/{tool_name}\n"})}),"\n",(0,s.jsx)(n.p,{children:"Examples:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"mcp://filesystem/read_file"}),": Reading a file through the filesystem MCP server"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"mcp://github/create_issue"}),": Creating a GitHub issue"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"mcp://database/execute_query"}),": Running a database query"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"mcp://shell/execute"}),": Executing a shell command"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"mcp://slack/send_message"}),": Sending a Slack message"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"next-steps",children:"Next Steps"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["See ",(0,s.jsx)(n.a,{href:"/docs/concepts/policies#governing-mcp-tool-calls",children:"Governing MCP tool calls"})," for detailed patterns."]}),"\n",(0,s.jsxs)(n.li,{children:["Learn about ",(0,s.jsx)(n.a,{href:"/docs/concepts/policies",children:"Policies"})," for writing governance rules."]}),"\n",(0,s.jsxs)(n.li,{children:["Explore the ",(0,s.jsx)(n.a,{href:"/docs/sdk/python",children:"Python SDK"})," or ",(0,s.jsx)(n.a,{href:"/docs/sdk/nodejs",children:"Node.js SDK"}),"."]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}},28453(e,n,r){r.d(n,{R:()=>i,x:()=>t});var o=r(96540);const s={},l=o.createContext(s);function i(e){const n=o.useContext(l);return o.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),o.createElement(l.Provider,{value:n},e.children)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.