Skip to main content
Glama
OrygnsCode

opa-mcp-server

Query OPA decision

opa_query_decision

Evaluate a policy decision by posting input to an OPA server at a specified data path and returning the rule result.

Instructions

Evaluate a decision against the running OPA server. POSTs to the data path with {input} and returns whatever the rule produces. Use this to ask the server "given this input, what does data.X.allow say?"

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pathYesDecision path under `data.`, e.g. "rbac/allow" or "rbac.allow".
inputNoInput document to evaluate against.
explainNoInclude a trace at the requested level.
metricsNoInclude metrics in the response.

Implementation Reference

  • The handler that executes the 'opa_query_decision' tool logic: registers the tool with MCP server, defines input schema (path, input, explain, metrics), and on invocation POSTs to OPA's /v1/data/{path} endpoint with the input document and optional explain/metrics query params, returning the result envelope.
    server.registerTool(
      'opa_query_decision',
      {
        title: 'Query OPA decision',
        description:
          'Evaluate a decision against the running OPA server. POSTs to the data path with `{input}` and returns whatever the rule produces. Use this to ask the server "given this input, what does data.X.allow say?"',
        inputSchema: {
          path: z
            .string()
            .min(1)
            .describe('Decision path under `data.`, e.g. "rbac/allow" or "rbac.allow".'),
          input: z.unknown().optional().describe('Input document to evaluate against.'),
          explain: z
            .enum(['notes', 'fails', 'full', 'debug'])
            .optional()
            .describe('Include a trace at the requested level.'),
          metrics: z.boolean().optional().describe('Include metrics in the response.'),
        },
      },
      async ({ path, input, explain, metrics }) => {
        return withToolEnvelope<{ result?: unknown; explanation?: unknown; metrics?: unknown }>(
          config,
          async () => {
            try {
              const query: Record<string, string | boolean> = {};
              if (explain) query['explain'] = explain;
              if (metrics) query['metrics'] = true;
              const data = await opa.request<{
                result?: unknown;
                explanation?: unknown;
                metrics?: unknown;
              }>({
                method: 'POST',
                path: dataPath(path),
                body: input !== undefined ? { input } : {},
                query,
              });
              return ok({
                result: data.result,
                explanation: data.explanation,
                metrics: data.metrics,
              });
            } catch (e) {
              return mapOpaClientError(e);
            }
          },
        );
      },
    );
  • Input schema definition for opa_query_decision using Zod: path (required string), input (optional unknown), explain (optional enum: notes/fails/full/debug), metrics (optional boolean).
    inputSchema: {
      path: z
        .string()
        .min(1)
        .describe('Decision path under `data.`, e.g. "rbac/allow" or "rbac.allow".'),
      input: z.unknown().optional().describe('Input document to evaluate against.'),
      explain: z
        .enum(['notes', 'fails', 'full', 'debug'])
        .optional()
        .describe('Include a trace at the requested level.'),
      metrics: z.boolean().optional().describe('Include metrics in the response.'),
    },
  • Top-level tool registration entry point that calls registerServerManagementTools, which in turn calls registerDecisionTools that registers opa_query_decision.
    export function registerTools(server: McpServer, config: Config): void {
      registerAuthoringTools(server, config);
      registerEvaluationTools(server, config);
      registerBundleTools(server, config);
      registerServerManagementTools(server, config);
      registerHelperTools(server, config);
    }
  • Category-D registration entry point that invokes registerDecisionTools to register the opa_query_decision tool.
    export function registerServerManagementTools(server: McpServer, config: Config): void {
      registerPolicyTools(server, config);
      registerDataTools(server, config);
      registerDecisionTools(server, config);
      registerStatusTools(server, config);
    }
  • Helper that converts a dotted or slashed decision path (e.g. 'rbac.allow' or 'data.rbac.allow') into a /v1/data/ URL path used in the OPA REST API call.
    function dataPath(path: string): string {
      const stripped = path.replace(/^data\./, '').replace(/^\/+/, '');
      return `/v1/data/${stripped.replace(/\./g, '/')}`;
    }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It explains the tool POSTs to the data path and returns rule output, implying a read-only query. However, it does not explicitly state that the operation has no side effects or whether any authentication is needed, leaving some behavioral ambiguity.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences long, front-loaded with the core action, and includes a usage example. Every sentence adds value with no redundancy or fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 4 parameters and no output schema, the description covers the main workflow (POST with input, returns rule output). It mentions the HTTP method and path. However, it doesn't explain the `explain` and `metrics` parameters or the response format, but given no output schema, this is a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds minimal extra meaning beyond the schema (e.g., mentioning `{input}` is sent to the data path). It does not elaborate on `explain` or `metrics`, but the schema already describes them, so this is adequate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Evaluate a decision against the running OPA server' and explains the HTTP method and data path. It distinguishes from siblings like opa_get_data (data retrieval without evaluation) and opa_patch_data (data modification) by focusing on decision evaluation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a clear usage example: 'Use this to ask the server "given this input, what does data.X.allow say?"'. However, it does not explicitly state when not to use this tool (e.g., for data retrieval or policy management) or mention alternatives, though the sibling tools imply them.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/OrygnsCode/opa-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server