# Approval MCP Server

[![Crates.io](https://img.shields.io/crates/v/mcp-approval.svg)](https://crates.io/crates/mcp-approval)
[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)
[![ADK-Rust Enterprise](https://img.shields.io/badge/ADK--Rust-Enterprise-purple.svg)](https://enterprise.adk-rust.com)
[![Registry Ready](https://img.shields.io/badge/ADK_Registry-Ready-green.svg)](https://www.zavora.ai)

A multi-stage **approval workflow engine** for [ADK-Rust Enterprise](https://enterprise.adk-rust.com) legal and media-content agents. 17 MCP tools: configurable workflow templates, stage rules (all-of / any-of / quorum), decisions with delegation and escalation, SLA/expiry clocks, and an immutable audit trail on every action.

## Yes — this is the approval-workflow server

An approval system *is* a workflow engine. One model — an `ApprovalRequest` moving through an ordered set of `Stage`s, each with a decision rule and eligible approvers — serves every agent below. The variety is in the routing, not the mechanics.

| Domain | Agent | Typical workflow shape |
|--------|-------|------------------------|
| **Legal** | Board Consent Drafter | single stage, **quorum** (N-of-M directors) |
| **Legal** | Contract Review Agent | **sequential** Legal → Finance → Exec |
| **Legal** | Policy Compliance Reviewer | compliance **sign-off** gate |
| **Media** | Brand Compliance Reviewer | brand **any-of** review |
| **Media** | Content Localization Agent | linguistic QA → in-country review |
| **Media** | Publishing QA Agent | editorial QA gate |
| **Media** | Rights Clearance Assistant | rights review → legal clearance |
| **Media** | Social Post Producer | fast content review before publish |

## Architecture

<p align="center">
  <img src="https://raw.githubusercontent.com/zavora-ai/mcp-approval/main/docs/architecture.svg" alt="Approval MCP Architecture" width="750"/>
</p>

## Core Concepts

- **Workflow template** — a reusable, ordered list of stages for a request type. Eight defaults ship (one per agent above); create your own with `create_workflow`.
- **Stage rule** — how a stage resolves from its votes:
  - `all_of` — every eligible approver must approve
  - `any_of` — one approval advances
  - `quorum` — at least N approvals (e.g. 3 of 5 directors)
- **Decision** — `approve` · `reject` · `request_changes` · `abstain`. A reject fails the request; request-changes bounces it back to the requester for resubmission.
- **Delegation** — an approver can delegate authority; the delegate's vote is recorded *on behalf of* the original (preserved in the audit trail).
- **Escalation** — reassign the active stage to new approvers (e.g. on SLA breach).
- **Audit trail** — every mutation appends an immutable entry (actor, action, timestamp). Essential for board consents and legal sign-offs.

## Tools (17)

### Agentic (2)

| Tool | What It Does |
|------|-------------|
| `intake_and_route` | Create **and** submit a request in one step, auto-selecting the default workflow for the type |
| `request_status` | Concise status: workflow position, approvals vs. needed, outstanding approvers, next step |

### Workflow Templates (3)

| Tool | What It Does |
|------|-------------|
| `list_workflows` | List templates (optionally by domain) |
| `get_workflow` | Get a template's full stage definitions |
| `create_workflow` | Define a custom workflow (stages, rules, approvers, SLAs) |

### Requests & Lifecycle (6)

| Tool | What It Does |
|------|-------------|
| `create_request` | Open a request bound to a workflow (optionally submit) |
| `get_request` | Full detail: stages, votes, comments, attachments, audit |
| `search_requests` | Filter by text, domain, type, status, approver |
| `submit_request` | Route a draft for review (activate first stage) |
| `cancel_request` | Withdraw a request (gated) |
| `escalate` | Reassign the active stage to new approvers (gated) |

### Decisions & Collaboration (6)

| Tool | What It Does |
|------|-------------|
| `decide` | Record a decision on the active stage; evaluates the rule (gated) |
| `my_queue` | Requests awaiting a given approver |
| `delegate` | Delegate approval authority for a request (gated) |
| `add_comment` | Comment on the request thread |
| `add_attachment` | Attach a document/evidence reference (by URI) |
| `get_audit_trail` | Immutable record of who did what, when |

## Example — board written consent (quorum 3 of 5)

```
> intake_and_route(domain: "legal", request_type: "board_consent",
    title: "Approve 2026 budget", requester: "secretary", subject_ref: "consent:BUDGET-2026")
  → routed AR-1003 · active stage "Board Vote" (quorum)

> decide(id: "AR-1003", approver: "dir.1", decision: "approve")   → in_review (1 of 3)
> decide(id: "AR-1003", approver: "dir.2", decision: "approve")   → in_review (2 of 3)
> decide(id: "AR-1003", approver: "dir.3", decision: "approve")   → approved  (quorum met)

> get_audit_trail(id: "AR-1003")
  → created · submitted · decision ×3 · stage_approved · approved
```

## Example — contract review (sequential, with delegation)

```
> create_request(request_type: "contract_review", title: "MSA with Acme",
    requester: "legalops", subject_ref: "contract:MSA-ACME", submit: true)
  → AR-1010 · stage "Legal Review"

> delegate(id: "AR-1010", from: "legal.counsel", to: "legal.associate", reason: "OOO")
> decide(id: "AR-1010", approver: "legal.associate", decision: "approve")
  → advances to "Finance Review"  (vote recorded on behalf of legal.counsel)
```

## Installation

### 1. Build

```bash
git clone https://github.com/zavora-ai/mcp-approval
cd mcp-approval
cargo build --release
```

### 2. Add to your MCP client

**Claude Desktop / Kiro / Cursor / Windsurf:**
```json
{
  "mcpServers": {
    "approval": {
      "command": "/path/to/mcp-approval"
    }
  }
}
```

### 3. Use it

```
> list_workflows(domain: "media_content")
> intake_and_route(domain: "media_content", request_type: "social_post",
    title: "Launch thread", requester: "social.producer", subject_ref: "post:LAUNCH-01")
```

## Governance & Data Handling

- **Gated writes** — `decide`, `cancel_request`, `escalate`, and `delegate` require approval in production (`requires_approval`); reads are `read_only`.
- **Defensible audit** — every state change is recorded immutably with actor and timestamp.
- **No raw documents** — items under approval and attachments are opaque references/URIs, never embedded content.
- **Integration scaffold** — the in-memory store is for development; back it with a durable store and bind `approver`/`actor` to authenticated identities in production.

## MCP Server Manifest

```toml
server_id = "mcp_approval"
display_name = "Approval Workflows"
version = "1.0.0"
domain = "governance"
risk_level = "high"
writes_allowed = "gated"
transports = ["stdio"]
```

## Contributors

<!-- ALL-CONTRIBUTORS-LIST:START -->
| [<img src="https://github.com/jkmaina.png" width="80px;" alt=""/><br /><sub><b>James Karanja Maina</b></sub>](https://github.com/jkmaina) |
|:---:|
<!-- ALL-CONTRIBUTORS-LIST:END -->

## License

Apache-2.0 — see [LICENSE](LICENSE) for details.

---

Part of the [ADK-Rust Enterprise](https://enterprise.adk-rust.com) MCP server ecosystem.

## Registry Compliance

This server implements the [ADK MCP SDK](https://crates.io/crates/adk-mcp-sdk) contract:

- **HealthCheck** — async health probe for registry monitoring
- **mcp-server.toml** — manifest declaring tools, risk classes, and approval gates
- **Structured tracing** — `RUST_LOG` env-filter for observability
