Skip to main content
Glama
ACP Governance MCP Server

ACP Governance MCP Server

Official
README.md
# acp-mcp-server

An MCP server that lets Claude, ChatGPT, Cursor and other MCP clients ask [Agentic Control Plane](https://agenticcontrolplane.com) whether a tool call would be allowed, and read their own workspace's status.

If you use a coding agent with the ACP hook installed ([acp-install](https://github.com/agentic-control-plane/acp-install)), tool calls are already checked automatically. You need this server for MCP clients that have no hook, such as Claude.ai and ChatGPT.

**Limit:** `acp_check` is advisory. The client has to call it, and nothing stops a client that doesn't. It returns `allow`, `deny` or `cant_predict`, and a call that needs a person's approval comes back as `deny` with "requires human approval" in the reason. If the gateway can't read your policy it answers `allow` with `governed: false`. The self-hosted bridge also answers `allow` (reason `acp-network-error` or `acp-http-error`) when it can't reach the gateway. Either way it fails open. For enforcement you need the hook.

## Connect

The hosted server is at **`https://api.agenticcontrolplane.com/mcp`**. Add it as a connector in your MCP client.

**Claude Desktop and Claude.ai:**
```
URL: https://api.agenticcontrolplane.com/mcp
Auth: OAuth (you sign in through ACP)
```

**ChatGPT, Cursor, Cline and other MCP clients:** add the same URL. Clients that support MCP OAuth sign you in the same way; for the rest, use a bearer key as below.

**Your own agent code:**
```http
POST https://api.agenticcontrolplane.com/mcp
Authorization: Bearer gsk_<your-acp-api-key>
Content-Type: application/json
```

You need an ACP workspace. Free up to 5 initiating agents, with unlimited calls. Sign up at [cloud.agenticcontrolplane.com/login](https://cloud.agenticcontrolplane.com/login).

## Tools

The hosted endpoint serves these eleven tools by default; a workspace with a customised tool allowlist may show fewer. None of them can approve a held call or apply a policy.

| Tool | What it does |
|---|---|
| `acp_check` | Would this call be allowed? Returns `allow`, `deny` or `cant_predict`, plus a reason. Advisory (see the limit above). |
| `acp_status` | Check the connection and your workspace identity and mode. |
| `acp_audit`, `acp_cost`, `acp_optimize`, `acp_trace`, `acp_usage`, `acp_recommendations` | Read your workspace's own audit, spend and savings data. |
| `acp_propose_rule` | Draft a policy rule. A human confirms it in the console. It never applies policy itself. |
| `acp_wait_approval` | Wait for a person to decide a held call, then report approved, denied, expired or pending. It never approves anything. |
| `acp_deny_approval` | Withdraw a pending hold you raised. It can only stop a call. |

The source in this repo (`src/tools/tools.ts`) defines only `acp_check`, `acp_status` and `acp_permission_prompt`. The hosted endpoint is the reference. If you self-host this repo, you get those three, not the hosted set above.

## Self-host

For air-gapped setups, or to point at a self-hosted ACP gateway:

```bash
git clone https://github.com/agentic-control-plane/acp-mcp-server
cd acp-mcp-server
npm install
npm run build

# Point at the ACP API (default: https://api.agenticcontrolplane.com)
export ACP_API_BASE=https://your-acp-gateway.example.com

# Required: the OAuth issuer that signs your users' tokens
# (the server refuses to start without it)
export OAUTH_ISSUER=https://your-tenant.us.auth0.com

# Optional: service-level API key for OAuth users (ChatGPT, Claude.ai)
# whose JWTs aren't directly usable as ACP tokens
export ACP_SERVICE_KEY=gsk_workspace_...

npm start
# MCP endpoint:   POST http://0.0.0.0:3000/mcp
# OAuth discovery: GET /.well-known/oauth-protected-resource
```

The bridge speaks streamable-HTTP MCP and forwards to ACP's `/govern/tool-use` endpoint.

## How a call flows

```
your AI client        this MCP server           ACP gateway
Claude / ChatGPT  ->  api.agenticcontrolplane  ->  POST /govern/tool-use
Cursor / Cline        POST /mcp (acp_check)         policy + audit + identity
                                                    -> allow / deny / ask
```

Each call writes an audit row. On the hosted endpoint it's attributed to the signed-in person; a self-hosted bridge using `ACP_SERVICE_KEY` attributes calls to that key. One workspace shows every governed call from every MCP client your team uses.

## Auth

1. **OAuth** for human-driven clients (Claude.ai, ChatGPT). The client signs in against ACP's identity provider, and the Auth0 JWT identifies the person. The bridge uses an `ACP_SERVICE_KEY` to make the governance call on their behalf.
2. **Bearer `gsk_` API key** for programmatic clients. The key's identity is the actor. No OAuth.

OAuth discovery metadata is at `/.well-known/oauth-protected-resource`, per the MCP authorization spec.

## Develop

```bash
npm install
npm run dev        # tsx hot reload
```

Tools: `src/tools/tools.ts`. JSON-RPC handler: `src/handlers/mcpHandler.ts`. Express entry point and rate limits: `src/server/expressServer.ts`.

## Links

[ACP](https://agenticcontrolplane.com) · [Sign up](https://cloud.agenticcontrolplane.com/login) · [AgentGovBench](https://github.com/agentic-control-plane/agentgovbench) · [Issues](https://github.com/agentic-control-plane/acp-mcp-server/issues) · MIT, see [LICENSE](LICENSE) · Email: su***************************om