Model Context Protocol server for Open Policy Agent (OPA). Author, validate, debug, and explain Rego policies through any MCP-compatible client.
OPA MCP Server
以下摘录自该仓库的 README(片段) · 在 GitHub 读完整 README →
A Model Context Protocol (MCP) server
that turns any MCP-compatible client (Claude Desktop, Claude Code, Cursor,
VS Code, Windsurf, Zed, and others) into a first-class
Open Policy Agent and Rego authoring
environment.
json
{
"mcpServers": {
"opa": {
"command": "npx",
"args": ["-y", "@orygn/opa-mcp"],
"env": {
"OPA_BINARY": "/usr/local/bin/opa",
"REGAL_BINARY": "/usr/local/bin/regal",
"OPA_URL": "http://localhost:8181",
"OPA_MCP_ALLOWED_PATHS": "/path/to/your/policies"
}
}
}
}
bash
npx -y @smithery/cli install @orygn/opa-mcp --client claude
bash
claude mcp add \
--env OPA_BINARY=/usr/local/bin/opa \
--env REGAL_BINARY=/usr/local/bin/regal \
--env OPA_MCP_ALLOWED_PATHS=/path/to/your/policies \
opa -- npx -y @orygn/opa-mcp
bash
npm install -g @orygn/opa-mcp
opa-mcp --version
bash
docker pull orygn/opa-mcp:latest
docker run --rm -i \
-v /path/to/your/policies:/policies:ro \
-e OPA_MCP_ALLOWED_PATHS=/policies \
orygn/opa-mcp
bash
which opa && which regal # macOS / Linux
powershell
Get-Command opa, regal | Select-Object Source # Windows
json
{ "ok": true, "data": { ... }, "warnings": [ ... ] }
{ "ok": false, "error": { "code": "INVALID_REGO", "message": "...", "hint": "...", "details": { ... } } }
jsonc
// Input
{
"source": "package x\nallow if input.user==\"admin\""
}
// Output (ok)
{
"ok": true,
"data": {
"formatted": "package x\n\nallow if input.user == \"admin\"\n",
"changed": true
}
}
jsonc
// Input
{
"source": "package x\nallow if y",
"strict": true
}
// Output (error path; the JSON diagnostics arrive on stderr from opa)
{
"ok": true,
"data": {
"valid": false,
"errors": [
{
"code": "rego_unsafe_var_error",
"message": "var y is unsafe",
"location": { "row": 2, "col": 11 }
}
]
}
}
jsonc
// Input
{
"query": "data.rbac.allow",
"source": "package rbac\nimport rego.v1\nallow if input.role == \"admin\"",
"input": { "role": "admin" }
}
// Output
{
"ok": true,
"data": {
"result": [{ "expressions": [{ "value": true, "text": "data.rbac.allow", "location": { "row": 1, "col": 1 } }] }]
}
}
jsonc
// Input
{
"inlineConfig": "apiVersion: v1\nkind: Pod\nspec:\n containers:\n - name: app\n image: nginx:latest",
"inlinePolicy": "package main\ndeny contains msg if { input.spec.containers[_].image == \"nginx:latest\"; msg := \"pin your image tag\" }"
}
// Output
{
"ok": true,
"data": {
"passed": false,
"results": [
{
"filename": " ",
"namespace": "main",
"successes": 0,
"failures": [{ "msg": "pin your image tag" }],
"warnings": [],
"skipped": [],
"exceptions": []
}
],
"summary": {
"passed": 0,
"failed": 1,
"warnings": 0,
"skipped": 0,
"successes": 0,
"failures": 1
}
}
}
You: I need an authz policy: editors can read/write, viewers can only read,
admins can do anything.
Agent: I'll draft it. (calls rego_format on a draft, then rego_check, then
rego_lint)
Agent: (calls rego_eval with an inputs batch: each role, no role at all,
a role that is not a string, an unknown method)
Agent: Here's the policy. A request with no role, or a role that is not a
string, is denied. I kept those probes as tests next to one case per
role. (calls rego_generate_test_skeleton, fills in the stubs, then
rego_test)
Agent: All 9 tests pass. Want me to save it to ?
You: This API call is being denied and I don't know why.
[pastes input.json]
Agent: (calls rego_explain_decision against your local policy with that input)
Agent: The deny comes from rule forbid_anonymous_writes at line 17.
Specifically, input.user is null and the request method is "POST".