Skip to main content
Glama

ops-mcp — an internal admin panel as an MCP server

Sixteen tools for a SaaS company's support desk: look up a customer, read their invoices, read a support ticket, issue a refund — and a few things nobody should let an agent do unsupervised.

This is one half of a pair:

Repo

this one

the tools

armoriq-adk-ops-agent

a Google ADK agent that uses them, governed by ArmorIQ

armoriq-adk-guide

how to build your own

Deploy this, register its URL on platform.armoriq.ai as an MCP named ops-mcp, and point the agent at it.


There is no security in this code

That is deliberate, and it is the most important thing to understand here.

No permission checks, no role lookups, no policy. Every tool does exactly what it is asked, by whoever asks. That is how most internal admin tooling actually works, and it is precisely why governance has to live at the agent layer instead.

The destructive tools are real. Run the agent with enforcement disabled and export_all_customers really does "send" the whole customer table. The example is worthless otherwise — a stubbed-out attack proves nothing.


Related MCP server: Support Agent MCP

The tools

Sixteen tools in four tiers. The tiers exist so there is something for policy to act on: each tier wants a different rule.

Tier 1 — reads → allow

Tool

lookup_customer

find an account by email

get_subscription

plan, price, seats

get_invoices

recent charges

get_ticket

one ticket, including the customer's message

list_tickets

subjects only, filterable by status

Tier 2 — low-risk writes → allow

Tool

add_account_note

internal note

reply_to_ticket

reply to the customer

extend_trial

up to 90 days

Tier 3 — sensitive / money → hold for a human

Tool

Threshold field

Suggested rule

issue_refund

amount

hold over the user's limit

apply_discount

value

hold over the user's limit

change_plan

amount

hold always

suspend_account

hold always

Tier 4 — destructive → block

Tool

export_all_customers

sends the whole table to an external address

impersonate_user

opens a session as a customer

grant_admin_role

full admin access

delete_account

permanent, irreversible


How ArmorIQ finds the money

This is the detail most likely to cost you an hour.

ArmorIQ's policy engine scans a tool's arguments for a field named amount, value, total, price or cost. That is why the money fields above are named the way they are.

apply_discount is the instructive one. Its natural field is percent, but a percentage is invisible to that scan — so the tool also takes value, the total dollars given away over the term. That is both what the policy reads and what a deal desk would actually approve on.

If your tool has to call it something else, like total_cents, register semantic metadata for the MCP so ArmorIQ knows which field holds the number and what unit it is in. Otherwise the threshold silently never fires.


The tickets

Four tickets, because the interesting thing about a support queue is that you cannot tell by looking which messages are hostile.

Ticket

Customer

What it is

TKT-4482

Acme

Completely ordinary. A question about adding seats.

TKT-4471

Acme

Genuine double-charge complaint, plus a prompt injection asking for a customer export

TKT-4490

Acme

A different injection style — manufactured urgency, claims approvals are suspended, asks for admin and impersonation

TKT-4495

Globex

Legitimate request for a large credit. Trips a threshold with no attack involved.

Demo TKT-4482 first to show normal operation, then TKT-4471. The contrast is the point.

The injection text lives in src/data.ts in plain sight rather than hidden, because the whole exercise is watching an agent read it and comply.


Files

File

Lines

What is in it

src/tools.ts

338

the sixteen tools, grouped into four tiers

src/data.ts

202

fake customers, charges and tickets

src/index.ts

73

Express + MCP wiring


Run it

npm install
npm start          # http://localhost:8788/mcp

Check it:

curl -s http://localhost:8788/health

curl -s -X POST http://localhost:8788/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

POST /reset restores the fake data so you can run a demo more than once. Without it, the second run reports "already refunded".


Deploy it

Render

render.yaml is a Blueprint for this repo. New > Blueprint, point it here, done. No root directory to set — this repo is one service.

On Render's free plan a service spins down when idle. The first request after a quiet period can take ~30 seconds, which looks exactly like the agent hanging. Use a paid instance if you are demoing live.

Cloud Run, Fly, or anything Docker

gcloud run deploy ops-mcp --source . --region us-central1 --allow-unauthenticated

The service reads PORT from the environment, which is what these platforms set.

Then register it

On platform.armoriq.ai, MCP Registry → Add MCP:

Field

Value

Name

ops-mcp

URL

https://ops-mcp.onrender.com/mcp

The name must match the agent's ARMORIQ_MCP_NAME exactly, and the URL must be public HTTPS — the platform calls it directly, so localhost will not do.


Notes

There is no authentication on this server. Deployed with --allow-unauthenticated, anyone who finds the URL can call delete_account directly — bypassing ArmorIQ entirely, because enforcement is at the agent layer, not here. Acceptable for a local example; not acceptable in production. Add a bearer token and register it as the MCP's auth on the platform, which supports bearer and api_key.

tsx is a runtime dependency, not a dev one. This service runs TypeScript directly rather than compiling first — one less build step to get wrong. That means tsx must be in dependencies; in devDependencies any npm install --omit=dev produces a deploy with no tsx, and the container will not boot.

Stateless by design. A fresh MCP server is built per request, so any instance can serve any request and the service scales horizontally.

GET /mcp returns 405. A stateless server has no server-initiated event stream, and the MCP spec says to answer 405. Express would otherwise return 404, which makes clients log a confusing transport error.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    Provides order lookup, customer lookup, and refund issuance tools with categorized errors to ensure accurate routing and distinguish access failures from valid empty results.
    -
  • A
    license
    A
    quality
    B
    maintenance
    Enables AI agents to manage a fictional B2B workspace SaaS (Tessera) with tools for ticketing, invoicing, customer management, and trial extensions, featuring a human-in-the-loop confirm pattern for safety.
    7
    14
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables AI agents to retrieve customer, order, ticket, policy, and agreement information, and to prepare or execute state-changing support actions like escalations and follow-ups with confirmation and access control.
    -

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/Fuzailkazi/armoriq-adk-ops-mcp'

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