Skip to main content
Glama
AtlaSent-Systems-Inc

atlasent-mcp

Official

@atlasent/mcp-server

Authorize every AI agent tool call before it executes.

An MCP server that plugs into any Model Context Protocol-compatible agent (Claude Desktop, Cursor, Claude Code, Copilot, LangChain) and enforces a simple contract: no protected action runs until AtlaSent has authorized it. Denied calls never reach the target system. Allowed calls return a permit token you can verify afterwards to close the audit loop.

Ships with a local rules engine so you can run the full evaluate → act → verify flow in under a minute, with zero credentials. The hosted AtlaSent backend is a configuration swap, not a rewrite.

When an agent "gets stamped" before acting — a human submits, approves, or stamps the prepared work — that stamp is an authorization event. AtlaSent turns it into a permit you verify before execution. Human approval is one source of authority; a policy rule, a deployment gate, or a risk-engine decision are others. Every source produces the same thing: a verifiable permit.

Run the demo in 60 seconds

git clone https://github.com/AtlaSent-Systems-Inc/atlasent-mcp-server.git
cd atlasent-mcp-server
npm install
npm run build
npm run demo

You'll see five scenarios run end-to-end — two use cases in one demo:

Deploy gate (CI/CD pipelines):

Scenario A: agent attempts unauthorized deploy (prod, no approvals)
    [1] Agent calls deploy_service
    [2] MCP intercepts → calls authorize(ctx) → policy engine decides
    [3] Tool execution BLOCKED
        ✓ deploy did NOT run. The target system was not touched.
        ✓ reason: Production action 'production.deploy' requires at least one approval...

Scenario B: agent attempts authorized deploy (prod, with approval)
    [3] Tool execution PROCEEDS
        result: {"status":"deployed","service":"billing-api",...}

Scenario C: verify_permit closes the audit loop
    result: {"outcome":"verified","valid":true,...}

Agent tool call governance (MCP / AI-native builders):

Scenario D: agent evaluates agent.db.delete without a change window
    [1] Agent calls evaluate before running agent.db.delete
    [3] Tool execution HELD — awaiting human review
        ✓ database delete did NOT run. Queued for human review.

Scenario E: agent evaluates agent.search.web (safe read)
    [3] Tool execution PROCEEDS — agent searches the web
        ✓ web search authorized.
    [4] verify_permit closes the audit loop: {"outcome":"verified","valid":true}

AtlaSent governs any action_type — not just deploys. The same evaluate → permit → verify flow that gates CI/CD pipelines also governs your agent's database writes, web searches, and external API calls.

The demo uses local mode (no API key needed). To run the same demo against the hosted AtlaSent backend once your API key is issued:

ATLASENT_MODE=remote \
  ATLASENT_API_KEY=ask_live_xxx \
  ATLASENT_BASE_URL=https://api.atlasent.io/functions/v1 \
  ATLASENT_MCP_READONLY=1 \
  npm run demo

ATLASENT_BASE_URL defaults to https://api.atlasent.io/functions/v1. You can omit it unless you are on a self-hosted deployment.

ATLASENT_MCP_READONLY=1 is recommended for any live-API demo — see Read-only mode below.

Related MCP server: AgentWall

Agent tool call governance

AtlaSent is not a deploy gate product. It is execution-time authorization infrastructure. The action_type field is yours to define — any string your agent platform uses to name a tool invocation becomes a protected action.

Common agent action types:

// Database mutations
"agent.db.write"         // INSERT / UPDATE
"agent.db.delete"        // DELETE / TRUNCATE (destructive — triggers hold)

// External network calls
"agent.search.web"       // Read-only web search
"agent.api.post"         // Outbound POST to an external service

// File system
"agent.fs.write"         // Write or overwrite a file
"agent.fs.delete"        // Delete a file

// Code execution
"agent.code.execute"     // Run user-supplied code

Pattern — agent evaluates before every sensitive tool call:

// Before running a tool, the agent calls evaluate
const ctx = {
  action_type: "agent.db.delete",   // your action namespace
  actor_id: "agent:data-pipeline",   // which agent is acting
  environment: "production",
  // any context your policies need
};

const decision = await authorize(ctx);   // interception point
if (decision.decision !== "allow") {
  // Tell the LLM the tool was blocked and why
  return `Tool blocked: ${decision.reason}`;
}

// Run the tool
const result = await runDatabaseDelete(ctx);

// Close the audit loop
await verify(decision.permit_token, ctx);

If you are using LangChain, the @atlasent/guard package wraps this pattern as a one-liner decorator — see atlasent-sdk.

If you are building your own MCP server with protected tools, copy the deploy_service handler in src/server.ts — it is the canonical 20-line interception pattern. Wire atlasent_evaluate before any tool that writes, deletes, calls external APIs, or runs code.

Tools

atlasent_evaluate — evaluate an action against AtlaSent policies

Evaluate whether a subject is permitted to perform an action on a resource. Returns a decision (allow/deny/hold/escalate), a permit_token if allowed, an evaluation_id, and an optional reason.

Input:  { subject, action, resource, org_id, context? }
Output: { decision, permit_token?, evaluation_id?, reason?, ... }

Example:

{
  "subject": "user:alice",
  "action": "production.deploy",
  "resource": "env:prod",
  "org_id": "org_abc123",
  "context": { "ip": "10.0.0.1" }
}

atlasent_list_policies — list all policies for an organization

Returns all policies for the given org, optionally filtered by status.

Input:  { org_id, status? }   (status: "draft" | "shadow" | "enforce")
Output: array of policy objects

Example: { "org_id": "org_abc123", "status": "enforce" }

atlasent_get_policy — get a single policy by ID

Fetches the full policy definition for a given policy_id.

Input:  { policy_id, org_id }
Output: policy object

Example: { "policy_id": "pol_xyz789", "org_id": "org_abc123" }

atlasent_list_audit_events — query the audit event log

Query recent evaluation decisions. Use to verify that an evaluation was recorded or to investigate a sequence of decisions.

Input:  { org_id, evaluation_id?, from?, to?, limit? }
        (from/to: ISO 8601; limit: 1–100, default 20)
Output: array of audit event objects

Example:

{
  "org_id": "org_abc123",
  "from": "2025-01-01T00:00:00Z",
  "to": "2025-01-02T00:00:00Z",
  "limit": 50
}

atlasent_create_policy — create an authorization policy

Mutating tool — gated off when ATLASENT_MCP_READONLY=1.

Define a new authorization rule. New policies are created in draft state (no enforcement) and must be promoted to shadow or enforce to take effect.

Input:  { org_id, policy_id, title, policy_type, rules, description?, status?, ... }
Output: { policy_id, title, status, ... }

atlasent_update_policy — update an existing policy

Mutating tool — gated off when ATLASENT_MCP_READONLY=1.

Partial-update (PATCH) a policy's rules, metadata, or lifecycle status (e.g. promote draftenforce).

Input:  { policy_id, org_id, title?, rules?, status?, ... }
Output: { policy_id, status, ... }

atlasent_delete_policy — permanently delete a policy

Destructive tool — gated off when ATLASENT_MCP_READONLY=1.

Irreversibly remove a policy. Prefer setting status: "archived" via atlasent_update_policy when you only want to disable enforcement.

Input:  { policy_id, org_id }
Output: {} (empty on success)

atlasent_list_permits — list issued permits

Paginated list of permits for an organization, with optional filters by status, actor, action type, and time range.

Input:  { org_id, status?, actor_id?, action_type?, from?, to?, limit?, cursor? }
Output: { permits: [...], next_cursor? }

atlasent_revoke_permit — revoke an issued permit

Destructive tool — gated off when ATLASENT_MCP_READONLY=1.

Immediately invalidate a permit so subsequent verify calls fail with permit_revoked. Idempotent.

Input:  { permit_id, org_id, reason? }
Output: { revoked, permit_id, ... }

atlasent_permit — issue a permit token out-of-band

Mutating tool — gated off when ATLASENT_MCP_READONLY=1.

Mint a time-limited permit for a subject/action/resource outside of the standard evaluate flow — for example when a human pre-approves access.

Input:  { subject, action, resource, org_id, ttl_seconds?, context? }
Output: { permit_token, expires_at?, ... }

atlasent_verify_permit — verify a permit token (v1 REST)

Verify a permit token is currently valid for a given subject/action/resource. Use after completing an authorized action to close the audit loop.

Input:  { permit_token, org_id, action?, resource? }
Output: { valid, outcome, reason? }

atlasent_create_approval_request — request human approval

Submit an action for human sign-off. Call when atlasent_evaluate returns hold or when the agent knows approval is required. Do not proceed until resolved.

Input:  { subject, action, resource, org_id, justification?, context? }
Output: { approval_request_id, status, created_at, ... }

atlasent_resolve_approval_request — approve or deny a request

Approve or deny a pending approval request on behalf of a human reviewer.

Input:  { approval_request_id, org_id, resolution, resolver_id, comment? }
        (resolution: "approve" | "deny")
Output: { approval_request_id, status, resolver_id, ... }

atlasent_record_execution_evaluation — record execution outcome

Record the outcome of an authorized action to complete the full audit loop: evaluate → execute → record.

Input:  { evaluation_id, org_id, outcome, executed_at?, details? }
        (outcome: "success" | "failure" | "skipped")
Output: { execution_id, outcome, recorded_at, ... }

atlasent_create_webhook — register a webhook

Mutating tool — gated off when ATLASENT_MCP_READONLY=1.

Subscribe an external HTTPS endpoint to real-time AtlaSent events (e.g. evaluation.deny, approval.requested, permit.revoked).

Input:  { org_id, url, events, description?, secret? }
Output: { webhook_id, url, events, secret?, ... }

atlasent_delete_webhook — remove a webhook

Destructive tool — gated off when ATLASENT_MCP_READONLY=1.

Permanently deregister a webhook. AtlaSent stops sending events to that URL immediately.

Input:  { webhook_id, org_id }
Output: {} (empty on success)

evaluate — for agents that gate themselves (local/remote mode)

The agent calls evaluate before any sensitive action and respects the decision.

Input:  { action_type, actor_id, environment, approvals?, change_window? }
Output: { decision: "allow" | "deny" | "hold", permit_token?, reason?, audit_id?, ... }

verify_permit — close the audit loop

After the action runs, the agent calls verify_permit with the issued token.

Input:  { permit_token, action_type, actor_id, environment, ... }
Output: { outcome: "verified" | "expired" | "invalid" | "error", valid: boolean, ... }

deploy_service — demo of the interception pattern

A protected tool that authorizes itself before executing. Every call:

  1. Builds an action context from the tool arguments

  2. Calls authorize(ctx)this is the interception point

  3. If the decision is anything other than allow, returns the decision and does NOT execute

  4. On allow, runs the deploy and returns the result plus the permit token

See src/server.ts (the deploy_service handler) for the exact 20-line pattern every protected tool should follow. In production, your domain tools live on other MCP servers and call AtlaSent's evaluate tool before executing; this demo co-locates them so you can see the full flow today.

Execution Flow

  ┌─────────────┐
  │    Agent     │  wants to call a protected tool
  └─────┬───────┘
        │
        ▼
  ┌───────────────────────┐
  │    Protected tool       │
  │  (e.g. deploy_service)  │
  └─────┬───────────────────┘
        │ (1) build ActionContext
        ▼
  ┌─────────────────┐       ┌──────────────────────────┐
  │  authorize(ctx)  │──────▶│  engine (local | remote)  │
  └─────┬───────────┘       └────────┬─────────────────┘
        │ (2) Decision               │
        │   allow | deny | hold      │
        ▼                            ▼
  ┌────────────────────────────────────┐
  │  decision === "allow"?                    │
  └──┬───────────────────────┬───────────────┘
     │ no                    │ yes
     ▼                       ▼
  BLOCKED              (3) execute the action
  return decision            │
                             ▼
                      (4) return { decision, permit_token, result }
                             │
                             ▼
                      later: verify_permit closes the audit loop

The interception point is step (2): authorize() runs before the action. That's the entire guarantee — if decision !== "allow", the action does not run.

Decision envelope

Every authorization result uses the same shape, so agents and hosts handle all outcomes uniformly:

type Decision =
  | { decision: "allow";  permit_token: string; audit_id?: string; conditions?: string[] }
  | { decision: "deny";   reason: string;       audit_id?: string }
  | { decision: "hold";   reason: string;       hold_id?: string; audit_id?: string };

Verification has a parallel shape:

type VerifyResult = {
  outcome: "verified" | "expired" | "invalid" | "error";
  valid: boolean;
  reason?: string;
  audit_id?: string;
};

Handling each case:

Decision

Agent behavior

allow

Proceed. Pass permit_token to verify_permit after completing the action.

deny

Do not proceed. Surface reason to the user.

hold

Do not proceed. Tell the user the action is queued for human review; reference hold_id.

verification failure (verify returns valid: false or outcome: "error")

Flag the action for review. Something happened outside policy.

Local vs Remote mode

The engine behind authorize() is pluggable. The same tool handlers work in both modes — swapping the backend is a configuration change.

Mode

When selected

What it does

local

ATLASENT_MODE=local, or both ATLASENT_API_KEY and ATLASENT_BASE_URL are unset

Runs a small in-process rules engine (src/localEngine.ts) — no network, no credentials

remote

ATLASENT_MODE=remote, or both ATLASENT_API_KEY and ATLASENT_BASE_URL are set

Calls the hosted AtlaSent backend at POST /v1-evaluate and POST /v1-verify-permit

Local rules (for demos):

  1. Production action + no approvals → deny

  2. Destructive action (delete, drop, destroy, truncate, purge, wipe, rm) + no change_windowhold

  3. Otherwise → allow (with a pt_local_* permit valid for 5 minutes)

Environment variables:

Variable

Required

Default

Purpose

ATLASENT_MODE

no

auto-detect

Force local or remote

ATLASENT_API_KEY

remote only

Bearer token for the hosted API (prefix: ask_live_ / ask_test_)

ATLASENT_BASE_URL

no

https://api.atlasent.io/functions/v1

AtlaSent API base URL. Leave unset to use the hosted SaaS endpoint. Override only for self-hosted deployments.

ATLASENT_ANON_KEY

no

Optional x-anon-key header

ATLASENT_MCP_RATE_LIMIT

no

600

Per-tool calls per minute (token bucket)

ATLASENT_MCP_READONLY

no

(unset)

If 1 or true, skip registration of the 7 mutating tools. Recommended for live-API demos. See Read-only mode.

Read-only mode (for live demos)

In local mode, every tool either calls the in-process rules engine or short-circuits with no side effects, so it doesn't matter what the agent tries to do. The story is different the moment you point the server at a live AtlaSent backend with ATLASENT_MODE=remote and a real API key: the mutating CRUD tools call the hosted API directly. They do not go through the authorize() interception. An adversarial prompt, a hallucinated "let me clean up" step, or a tool-misuse mistake by the agent can damage real demo-org state.

Set ATLASENT_MCP_READONLY=1 (or true) and the server will skip registration of these 7 tools at startup:

  • atlasent_create_policy

  • atlasent_update_policy

  • atlasent_delete_policy

  • atlasent_create_webhook

  • atlasent_delete_webhook

  • atlasent_revoke_permit

  • atlasent_permit

Everything else stays available, including the full demo flow:

  • The agent-gating loop (evaluateverify_permit) and the protected-tool demo (deploy_service)

  • All read tools (atlasent_list_policies, atlasent_get_policy, atlasent_list_permits, atlasent_list_audit_events, atlasent_evaluate, atlasent_verify_permit)

  • The approval-request workflow (atlasent_create_approval_request, atlasent_resolve_approval_request, atlasent_record_execution_evaluation)

On startup, the server emits a server.readonly_mode structured log line to stderr listing the disabled tools so the operator can confirm the gate is active.

When to enable: any live demo (customer call, conference, screencast) that uses a real API key — even on a dedicated demo org. The cost is zero (the read flow, the approval flow, and the deploy_service proof all stay functional); the upside is that no LLM mishap can destroy live state. Disable the flag only when you are intentionally exercising the mutating tools from a trusted operator console.

Claude Desktop config

{
  "mcpServers": {
    "atlasent": {
      "command": "npx",
      "args": ["-y", "@atlasent/mcp-server"],
      "env": {
        "ATLASENT_MODE": "remote",
        "ATLASENT_API_KEY": "ask_live_xxxxxxxxxxxxxxxx",
        "ATLASENT_BASE_URL": "https://api.atlasent.io/functions/v1",
        "ATLASENT_MCP_READONLY": "1"
      }
    }
  }
}

Location: ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows).

Remove ATLASENT_MCP_READONLY from env only when you intend to use the mutating CRUD tools from a trusted operator session.

Cursor config

Add to .cursor/mcp.json in your project root (or ~/.cursor/mcp.json globally), same shape as above.

Claude Code

claude mcp add atlasent -- npx -y @atlasent/mcp-server
export ATLASENT_API_KEY=ask_live_xxxxxxxxxxxxxxxx
export ATLASENT_BASE_URL=https://api.atlasent.io/functions/v1  # omit to use the default SaaS endpoint
export ATLASENT_MCP_READONLY=1   # safe default; unset for ops sessions

Fail-closed guarantees

Every error path collapses to { decision: "deny" }:

  • API unreachable → deny

  • Request timeout (10s) → deny

  • Malformed response → deny

  • Remote returns allow without a permit_tokendeny

  • Unknown/invalid decision string → deny

  • Verify returns an unrecognized verify_error_codeinvalid (treated as not valid)

The agent never proceeds without an explicit allow.

How the hosted backend plugs in

Nothing in the tool handlers changes when you move from local to remote. The deploy_service handler calls authorize(ctx); authorize() reads ATLASENT_MODE on every call and picks the engine. Switching to the hosted backend is three env vars.

The remote adapter (src/engine.ts) speaks the AtlaSent API shape directly.

  • POST /v1-evaluate

    • request: { action_type, actor_id, context } — flat top-level fields. mcp-server passes environment, approvals, and change_window inside context so policy expressions can read them.

    • response: { decision, permit_token?, request_id, expires_at?, denial?, ... } — top-level permit_token (raw UUID) is exposed to MCP hosts as the MCP envelope's permit_token; request_id becomes audit_id.

  • POST /v1-verify-permit

    • request: { permit_token, action_type, actor_id }

    • response: { valid, outcome: "allow" | "deny", verify_error_code?, reason? } — server outcome === "allow" becomes verified; verify_error_code is mapped to expired / invalid / error and falls through to invalid for anything unrecognized.

Development

npm install
npm run build              # compile TypeScript
npm test                   # 26 unit tests (local + remote mocked) + readonly-mode tests
npm run test:integration   # requires ATLASENT_API_KEY + ATLASENT_BASE_URL; skips otherwise
npm run demo               # end-to-end authorization demo (local mode)

License

MIT

Install Server
A
license - permissive license
A
quality
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
1Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

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/AtlaSent-Systems-Inc/atlasent-mcp-server'

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