Metadata-Version: 2.4
Name: dmint-cli
Version: 1.0.1
Summary: CLI tooling for Dmint policy creation, compilation, and management
Author: Dmint Authors
License-Expression: Apache-2.0
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Compilers
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: dmint<2.0.0,>=1.0.0
Requires-Dist: mcp<3.0.0,>=2.2.0
Provides-Extra: test
Requires-Dist: pytest>=8.0.0; extra == "test"
Dynamic: license-file

# dmint-cli (v1.0.1)

> **Developer tooling for interactive discovery, authoring, compilation, and offline verification of Dmint security policies and MCP protection artifacts.**

`dmint-cli` bridges the gap between natural language security requirements (`access.md`) and deterministic, schema-enforced Dmint authorization policies (`policy.json`) and runtime MCP protection configurations (`mcp_protection.json`).

```text
                                  dmint-cli
                                      │
               ┌──────────────────────┼──────────────────────┐
               │                      │                      │
         create-policy        create-mcp-policy        verify-policy
               │                      │                      │
        ┌──────┴──────┐         MCP Tool Discovery      100% Offline
        │             │               │                 LLM-Free / Zero Network
      Local          MCP        ┌─────┴────────────┐         │
      Tools         Tools       │                  │         ▼
        │             │       stdio        Streamable HTTP   Exit 0 / 1 / 2 / 3
   Static AST       stdio       │                  │
        │             │   subprocess handshake  PRM / RFC 8414 OAuth
        └──────┬──────┘         │                  │
               │                └─────────┬────────┘
               ▼                          ▼
       Multi-Turn Dialogue          tools/list
       with LLM Provider                  │
               │                          ▼
               └──────────────────► Candidate Policy
                                          │
                                   Human Review &
                               Policy.from_mapping()
                                          │
                               ┌──────────┴──────────┐
                               ▼                     ▼
                          policy.json       mcp_protection.json
                               │                     │
                               └──────────┬──────────┘
                                          ▼
                                dmint-mcp Enforcement
```

---

## Table of Contents

1. [What dmint-cli Does](#1-what-dmint-cli-does)
2. [What Problem It Solves](#2-what-problem-it-solves)
3. [Installation](#3-installation)
4. [Quickstart](#4-quickstart)
5. [General Policy Authoring (`create-policy`)](#5-general-policy-authoring-create-policy)
6. [Specialized MCP Policy Wizard (`create-mcp-policy`)](#6-specialized-mcp-policy-wizard-create-mcp-policy)
7. [Deterministic Offline Verification (`verify-policy`)](#7-deterministic-offline-verification-verify-policy)
8. [stdio MCP Transport](#8-stdio-mcp-transport)
9. [Streamable HTTP MCP Transport](#9-streamable-http-mcp-transport)
10. [Authenticated MCP Servers](#10-authenticated-mcp-servers)
11. [OAuth 2.0 Browser Authentication Flow](#11-oauth-20-browser-authentication-flow)
12. [Credentials & Secret Storage Model](#12-credentials--secret-storage-model)
13. [Generated Artifacts](#13-generated-artifacts)
14. [Relationship with dmint and dmint-mcp](#14-relationship-with-dmint-and-dmint-mcp)
15. [Multi-MCP Server Setup](#15-multi-mcp-server-setup)
16. [Failure Behavior & Stable Exit Codes](#16-failure-behavior--stable-exit-codes)
17. [Known Limitations](#17-known-limitations)
18. [Security Model & Threat Hardening](#18-security-model--threat-hardening)
19. [Non-Goals](#19-non-goals)
20. [Troubleshooting & Common Errors](#20-troubleshooting--common-errors)

---

## 1. What dmint-cli Does

`dmint-cli` is the developer-facing CLI suite and interactive assistant for the Dmint authorization framework:
- **Discovers Capabilities**: Inspects local Python tool code via static AST analysis (zero execution) or queries downstream Model Context Protocol (MCP) servers live over `stdio` and HTTP transports.
- **Authors Least-Privilege Policies**: Converts high-level English access rules (`access.md`) into formal Dmint policies via an interactive multi-turn dialogue with LLM providers.
- **Validates Policy Invariants**: Enforces strict semantic constraints, rejecting unknown fields, ambiguous patterns, and schema violations.
- **Generates Runtime Protection Configs**: Produces multi-integration binding manifests (`mcp_protection.json`) for seamless handoff to `dmint-mcp` enforcement proxies.
- **Verifies Policies Offline**: Provides instant, deterministic, zero-network schema verification via `dmint verify-policy`.

---

## 2. What Problem It Solves

AI agents equipped with tool-calling capabilities (e.g., database clients, cloud CLIs, filesystem utilities) introduce severe security vulnerabilities:
- **Prompt Injection**: Malicious untrusted inputs can trick agents into executing unauthorized actions (e.g., dropping database tables or exfiltrating files).
- **Over-Privileged Tool Access**: Agents are frequently given broad wildcard access when they only require granular, parameter-constrained operations.
- **Difficult Policy Authoring**: Writing correct, mathematical access-control policies with argument-level validation rules by hand is tedious and error-prone.

`dmint-cli` solves this by automating capability discovery, prompting developers interactively to resolve permission ambiguities, and outputting deterministic, verifiable policy files that can be audited before deployment.

---

## 3. Installation

### Requirements
- Python 3.10 or higher
- Linux, macOS, or Windows

### Install via pip

```bash
pip install dmint-cli
```

### Install with Test Dependencies

```bash
pip install "dmint-cli[test]"
```

---

## 4. Quickstart

Verify your installation and version:

```bash
dmint --version
# dmint 1.0.1
```

### 3-Step Walkthrough

#### Step 1: Define Intent (`access.md`)
Create a markdown file describing your access control rules:

```markdown
# Ops Bot Access Rules
- The agent may read rows from the 'analytics' database.
- Any writes, deletions, or schema updates require explicit human approval.
- Direct drop operations on production tables are denied.
```

#### Step 2: Author Policy Interactively
Run the wizard against your tools or downstream MCP server:

```bash
export OPENAI_API_KEY="sk-..."
dmint create-policy -f access.md -o policy.json --tools ./my_tools/
```

Review the candidate policy, resolve any clarifications, and confirm creation.

#### Step 3: Verify Offline
Verify the policy deterministically without network or LLM access:

```bash
dmint verify-policy policy.json
# ✓ Verified policy.json: 3 rule(s)
#   [ALLOW] tool='db', action='read', resource='NoResource'
#   [APPROVAL_REQUIRED] tool='db', action='write', resource='NoResource'
#   [DENY] tool='db', action='drop', resource='NoResource'
```

---

## 5. General Policy Authoring (`create-policy`)

`dmint create-policy` is the primary interactive authoring command for both local source code and MCP tools.

```bash
dmint create-policy -f access.md -o policy.json [--tools <dir_or_file>]
```

### Key Capabilities
- **Static AST Discovery**: Inspects Python source code using Python's `ast.parse()`. Code is **never executed or imported**, preventing malicious tools from running arbitrary code during policy generation.
- **Multi-Turn Dialogue Envelope**: Interacts with OpenAI, Gemini, Groq, OpenRouter, or local Ollama models. If requirements are ambiguous, the assistant asks targeted clarification questions before producing a policy.
- **Self-Correcting Validation Loop**: Automatically passes syntax or schema errors back to the LLM model to self-correct invalid policy mappings.
- **Deterministic Atomic Output**: Writes output files atomically using temporary files and directory fsyncs (`io_utils.py`), preventing partial or corrupted outputs.

### Flags & Options
| Flag | Description | Default |
| :--- | :--- | :--- |
| `-f, --file` | Path to natural language requirements file (markdown/text) | *Required* |
| `-o, --output` | Destination path for verified `policy.json` | *Required* |
| `--tools` | Path to tool source file or directory for AST inspection | `None` |
| `-provider` | LLM provider (`openai`, `gemini`, `groq`, `openrouter`, `ollama`) | `openai` |
| `-base_url` | OpenAI-compatible API base URL | Provider default |
| `-api_key` | API key (or via `OPENAI_API_KEY`, `GEMINI_API_KEY`, etc.) | Env vars |
| `-model` | LLM model name | `gpt-4o-mini` |
| `--non-interactive` | Non-interactive mode (disables terminal prompt queries) | `False` |
| `-y, --yes` | Auto-confirm candidate policy without prompting | `False` |
| `--timeout` | HTTP request timeout in seconds | `60.0` |

---

## 6. Specialized MCP Policy Wizard (`create-mcp-policy`)

`dmint create-mcp-policy` connects directly to downstream MCP servers, queries their live capabilities via the official MCP protocol, authors policies, and outputs runtime protection configurations.

```bash
dmint create-mcp-policy \
  --command "mcp-server-postgres" \
  --args "postgresql://localhost/production" \
  --integration-id "postgres" \
  -f access.md \
  -o policy.json \
  --config-output mcp_protection.json
```

> [!NOTE]
> `dmint protect-mcp` is retained as a fully supported backward-compatibility alias for `dmint create-mcp-policy`.

### Flags & Options
| Flag | Description | Default |
| :--- | :--- | :--- |
| `--command` | Subprocess executable command (e.g. `npx`, `python`) | `None` |
| `--args` | Command arguments passed to subprocess | `[]` |
| `--integration-id` | Unique ID namespace for this MCP server | Derived from command |
| `--transport` | MCP transport type (`stdio`, `streamable-http`) | `stdio` |
| `--url` | Remote MCP endpoint URL (for remote transports) | `None` |
| `-f, --file` | Input requirements markdown file | `access.md` |
| `-o, --output` | Output verified `policy.json` | `policy.json` |
| `--config-output` | Output `mcp_protection.json` runtime configuration | `mcp_protection.json` |
| `-y, --yes` | Auto-confirm candidate policy without prompting | `False` |

---

## 7. Deterministic Offline Verification (`verify-policy`)

`dmint verify-policy` performs mathematical, 100% offline schema and semantic validation of an existing `policy.json` file.

```bash
dmint verify-policy policy.json
# or
dmint verify-policy -f policy.json
```

### Guarantees
- **Zero Network Access**: Opens no sockets, performs no DNS queries, and contacts no external servers.
- **Zero LLM Invocations**: Contains no heuristic or stochastic evaluation.
- **Deterministic Exit Code**:
  - `0`: Policy is valid and safe according to Dmint core schema rules.
  - `1`: Policy validation failed (e.g. invalid rule effect, unknown keys).
  - `2`: Usage or CLI syntax error.
  - `3`: Policy file not found.

---

### AI Coding Agent Skill Installation (`install-skill`)

To enable AI coding assistants (such as Google Antigravity, Gemini CLI, Claude Code, or Cursor) to create, modify, understand, and verify Dmint policies directly through chat, install the official Dmint skill:

```bash
# Interactive installation (prompts to choose or type destination):
dmint install-skill

# Non-interactive workspace installation (defaults to .agents/skills/):
dmint install-skill -y

# Install to specific directory:
dmint install-skill --dest .agent/skills
# or
dmint install-skill --target ./my-skills

# Global machine-wide installation:
dmint install-skill --global     # ~/.gemini/config/skills/
dmint install-skill --claude     # ~/.claude/skills/
```

#### Interactive Selection
When run without `--dest`, `dmint install-skill` displays a numbered menu and allows typing any directory path directly:
- **`[1]` `.agents/skills/`** (Default: standard workspace path discovered by Antigravity, Gemini CLI, and Cursor)
- **`[2]` `.agent/skills/`** (Alternative project workspace path)
- **`[3]` `~/.gemini/config/skills/`** (Global config for Gemini & Antigravity)
- **`[4]` `~/.claude/skills/`** (Global config for Claude Code)
- **`[5]` Type custom path** (Or type any directory path directly at the prompt)

---

## 8. stdio MCP Transport

For local tool servers, `dmint-cli` connects over standard input/output (`stdio`):
1. Spawns the MCP server executable as an isolated subprocess (`subprocess.Popen`).
2. Performs the standard MCP JSON-RPC protocol handshake (`initialize` and `notifications/initialized`).
3. Dispatches `tools/list` to discover all published tools, input schemas, and descriptions.
4. Generates canonical capability names namespaced by integration ID:
   ```text
   mcp.{integration_id}.{tool_name}
   ```
5. Terminates the discovery subprocess cleanly upon completion.

---

## 9. Streamable HTTP MCP Transport

For remote MCP endpoints, `dmint-cli` supports HTTP discovery:
- **Mandatory HTTPS**: Strictly requires TLS (`https://`) to protect tool metadata in transit.
- **Strict Same-Origin Redirects**: Forbids cross-origin redirects to prevent SSRF and credential mix-up attacks.
- **Streaming Negotiation**: Uses `Accept: application/json, text/event-stream` for live protocol negotiation.

> [!IMPORTANT]
> The `dmint-mcp` runtime enforcement proxy currently supports `stdio` subprocess downstream execution. If you discover remote HTTP MCP servers, configure a local stdio bridge or ensure upstream gateway proxying.

---

## 10. Authenticated MCP Servers

When an MCP endpoint responds with `401 Unauthorized` or `403 Forbidden`:
1. **RFC 9728 PRM Discovery**: Looks for the `WWW-Authenticate` header and resolves Protected Resource Metadata (PRM) via `/.well-known/oauth-protected-resource`.
2. **RFC 8414 AS Discovery**: Resolves the OAuth 2.0 Authorization Server metadata via `/.well-known/oauth-authorization-server`.
3. **Issuer Validation**: Enforces RFC 9207 issuer matching to prevent authorization server mix-up attacks.
4. **Dynamic Client Registration**: Performs RFC 7591 Dynamic Client Registration if the server supports it, advertising `client_name="dmint-cli"` and `software_version="1.0.1"`.

---

## 11. OAuth 2.0 Browser Authentication Flow

When user authentication is required:
1. **Port 0 Loopback Server**: Binds directly to `127.0.0.1` on an ephemeral OS-assigned port (port 0). This prevents local port collision attacks and socket-reuse vulnerabilities.
2. **RFC 7636 PKCE**: Generates a high-entropy cryptographically secure code verifier and `S256` code challenge.
3. **System Browser Authorization**: Launches the default OS web browser pointing to the server's authorization URL.
4. **Single-Use Callback Handler**: Captures the OAuth callback, matches `state` and `iss` parameters, exchanges the authorization code for tokens, and shuts down the loopback listener immediately.

---

## 12. Credentials & Secret Storage Model

`dmint-cli` manages sensitive tokens using an enterprise-grade credential architecture:
- **Storage Hierarchy**:
  1. *Primary*: System OS Keyring via `keyring` (macOS Keychain, Linux Secret Service, Windows Credential Locker).
  2. *Hardened File Fallback*: `~/.config/dmint/credentials.json`.
- **Strict POSIX Permissions**: Credential directories and files are strictly enforced with `0700` and `0600` permissions. Insecure permissions are automatically rectified.
- **Symlink Defenses**: Uses `os.O_NOFOLLOW` and inode verification (`lstat`) to prevent symlink replacement attacks.
- **Secret Redaction**: All API keys, bearer tokens, client secrets, and passwords are masked (`***` or `sk-...1234`) across logs, console stdout/stderr, and serialized artifacts.

---

## 13. Generated Artifacts

### 1. `policy.json`
The authoritative security policy evaluated at runtime by `dmint`:

```json
{
  "rules": [
    {
      "effect": "allow",
      "tool": "mcp.postgres.run_query",
      "action": "execute",
      "resource": "public_tables"
    },
    {
      "effect": "approval_required",
      "tool": "mcp.postgres.delete_rows",
      "action": "execute",
      "resource": "production_db"
    }
  ]
}
```

### 2. `mcp_protection.json`
The multi-integration runtime manifest consumed by `dmint-mcp`:

```json
{
  "policy_file": "policy.json",
  "integrations": [
    {
      "integration_id": "postgres",
      "command": "mcp-server-postgres",
      "args": ["postgresql://localhost/prod"],
      "transport": "stdio",
      "default_discovery": "hidden",
      "tool_bindings": {
        "run_query": {
          "capability": "mcp.postgres.run_query",
          "discovery": "exposed"
        }
      }
    }
  ]
}
```

---

## 14. Relationship with dmint and dmint-mcp

| Package | Role | Execution Phase | Dependencies |
| :--- | :--- | :--- | :--- |
| **`dmint`** | In-process authorization engine | Runtime | Pure Python (Zero dependencies) |
| **`dmint-cli`** | Developer policy authoring & verification CLI | Development / Build | `dmint`, `mcp` SDK |
| **`dmint-mcp`** | MCP proxy server and tool enforcement gateway | Runtime | `dmint`, `mcp` SDK |

> [!CAUTION]
> ### The Fundamental Enforcement Invariant
> **Dmint does not secure an MCP server if the agent can bypass the protected execution path and call the original capability directly.**
> 
> To enforce real security:
> 1. The downstream MCP server must **not** be exposed directly to the agent.
> 2. The agent's client configuration must target **only** the `dmint-mcp` proxy gateway.
> 3. Subprocess command environments and credentials must remain restricted to the proxy process.

---

## 15. Multi-MCP Server Setup

`dmint-cli` handles multi-server setups with zero namespace collision:
- **Namespaced Tool Capabilities**: Tools named `query` in both a Postgres server and a MySQL server become `mcp.postgres.query` and `mcp.mysql.query`.
- **Deterministic Ordering**: Integrations in `mcp_protection.json` are sorted deterministically by `integration_id` to guarantee reproducible byte-for-byte outputs across git commits.

---

## 16. Failure Behavior & Stable Exit Codes

`dmint-cli` adheres to a strict fail-closed contract. Every command exits with an unambiguous, documented status code:

| Code | Constant | Meaning |
| :---: | :--- | :--- |
| **0** | `SUCCESS` | Operation completed successfully |
| **1** | `POLICY_ERROR` | Policy validation failed or user rejected candidate |
| **2** | `USAGE_ERROR` | Invalid CLI arguments or malformed flags |
| **3** | `FILE_NOT_FOUND` | Required input file does not exist |
| **4** | `JSON_ERROR` | Malformed JSON in inputs or LLM response extraction failure |
| **5** | `OUTPUT_WRITE_ERROR` | Atomic write failure or read-back verification failed |
| **6** | `API_ERROR` | External LLM provider API failure or HTTP error |
| **7** | `RESOURCE_EXHAUSTION`| Input size, loop count, or response limit exceeded |
| **8** | `SECURITY_VIOLATION` | SSRF attempt, insecure credentials, or protocol mix-up |

---

## 17. Known Limitations

- **Static AST vs. Dynamic Code**: `create-policy --tools` inspects static AST trees. Dynamic metaprogramming (`setattr`, runtime decorators) will not expose inferred capabilities.
- **Single-Host Stdio Proxy**: `dmint-mcp` currently wraps local subprocesses via `stdio`. Remote HTTP endpoints must be accessed via network gateways or secure tunnels.
- **LLM Non-Determinism**: Because policy *authoring* uses LLM reasoning, output policies should always be reviewed by humans before writing production files.

---

## 18. Security Model & Threat Hardening

`dmint-cli` is hardened against hostile inputs:
- **SSRF Defenses**: Validates all URLs and rejects loopback, RFC 1918 private subnets, link-local addresses, multicast, and cloud metadata endpoints (`169.254.169.254`).
- **Resource Exhaustion Bounds**:
  - Maximum MCP integrations: `32`
  - Maximum tools per integration: `256`
  - Maximum pagination depth: `20`
  - Maximum tool name length: `128` characters
  - Maximum HTTP response size: `1 MB`
  - Maximum OAuth metadata size: `512 KB`
  - Maximum policy/credential file size: `1 MB`
- **Zero Plaintext Secrets**: Secrets are permanently scrubbed from exceptions, error messages, and log records.

---

## 19. Non-Goals

To maintain security focus and boundary clarity, `dmint-cli` explicitly does **not**:
- **Act as a Runtime Gateway**: Runtime enforcement is exclusively the job of `dmint` and `dmint-mcp`.
- **Run Background Daemons**: `dmint-cli` is an ephemeral CLI tool; it runs on-demand and exits.
- **Replace Human Approval**: Policies are proposed for human review; automated generation never auto-deploys unreviewed policies without explicit `--yes` flags.

---

## 20. Troubleshooting & Common Errors

### 1. `PolicyValidationError` on generation
- **Cause**: The LLM produced rules with unrecognized effects or illegal fields.
- **Fix**: Re-run the command; `dmint-cli` automatically provides error feedback to the model to correct itself.

### 2. `Security error: Refusing connection to private or cloud-metadata IP`
- **Cause**: The MCP server URL points to `169.254.169.254` or private LAN without explicit configuration.
- **Fix**: Use public HTTPS URLs or use local `stdio` transport.

### 3. `API connection failed`
- **Cause**: Invalid API key or unreachable provider endpoint.
- **Fix**: Ensure `OPENAI_API_KEY`, `GEMINI_API_KEY`, or `GROQ_API_KEY` is exported in your environment.

### 4. `Insecure permissions on credential file`
- **Cause**: Credential file has permissions wider than `0600`.
- **Fix**: Run `chmod 600 ~/.config/dmint/credentials.json` (the CLI will also attempt to auto-repair this).

---

## License

Licensed under the [Apache License, Version 2.0](LICENSE).
See the [`LICENSE`](LICENSE) file for the complete license text.
