PHP Point of Sale MCP by usefulapi
io.usefulapi/php-point-of-saleusefulapi.iostreamable-httpv1.1.0Scanned
Read PHP Point of Sale items, sales, customers and 138 reports; manage customers, items, expenses.
26 tools: 5 can delete or cancel things, 1 change things and 20 only read.
- Reads private data · 6
- Reads text others write · 26
- Can send data out · 0
- 2 findings
Anlyon alternative
6 of these tools change something. Run those as governed actions.
Declare what an action changes, and Anlyon puts it under a shared limit, binds every approval to the exact request, and grades the outcome. It works on any HTTPS API you can describe as an action.
Anlyon does not run, proxy or govern this MCP server. A tool your own code calls directly is not routed through Anlyon and is not governed by it.
Import an OpenAPI spec →Tools
Grouped by what each tool does, most consequential first. Open one for its reasons and full description; descriptions are the publisher's own words.
26 tools
Deletes or cancels 5Claude Code: deny
phppos_create_customerWRITE: create a customer in the store.Reads text others writeNo findings
Why it is in this group
- The name "phppos_create_customer" says "create": a word for a change.
- The server marks it destructive (destructiveHint: true).
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it WRITE: create a customer in the store. Store-account balance, credit limit and loyalty points cannot be set here. Needs a Read/Write API key. Retrying creates a duplicate (check phppos_list_customers first). The store's 'new customer' webhook, if configured, fires. POST /customers.
Annotations the server declares
- title: Create customer
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: true
phppos_create_expenseWRITE: record an expense in the store's books (description, amount and date).Reads text others writeNo findings
Why it is in this group
- The name "phppos_create_expense" says "create": a word for a change.
- The server marks it destructive (destructiveHint: true).
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it WRITE: record an expense in the store's books (description, amount and date). It affects expense and profit-and-loss reports. Needs a Read/Write API key. Retrying records it twice (check phppos_list_expenses first). POST /expenses.
Annotations the server declares
- title: Create expense
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: true
phppos_create_itemWRITE: create an inventory item (name required).Reads text others writeNo findings
Why it is in this group
- The name "phppos_create_item" says "create": a word for a change.
- The server marks it destructive (destructiveHint: true).
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it WRITE: create an inventory item (name required). Stock quantities are not set here. Needs a Read/Write API key. Retrying creates a duplicate (search with phppos_list_items first). The store's item webhooks, if configured, fire. POST /items.
Annotations the server declares
- title: Create item
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: true
phppos_update_customerWRITE: change fields of an existing customer; only the fields you pass are sent.Reads text others writeNo findings
Why it is in this group
- The name "phppos_update_customer" says "update": a word for a change.
- The server marks it destructive (destructiveHint: true).
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it WRITE: change fields of an existing customer; only the fields you pass are sent. Overwrites the current values. Needs a Read/Write API key. The store's 'edit customer' webhook, if configured, fires. POST /customers/{person_id}.
Annotations the server declares
- title: Update customer
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: true
phppos_update_itemWRITE: change fields of an existing item (for example its price, category or active state); only the fields you pass are sent.Reads text others writeNo findings
Why it is in this group
- The name "phppos_update_item" says "update": a word for a change.
- The server marks it destructive (destructiveHint: true).
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it WRITE: change fields of an existing item (for example its price, category or active state); only the fields you pass are sent. Overwrites the current values, and a price change applies to the next sale. Needs a Read/Write API key. The store's 'edit item' webhook, if configured, fires. POST /items/{item_id}.
Annotations the server declares
- title: Update item
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: true
Changes things 1Claude Code: ask
phppos_run_reportRun one of the store's reports and return it (title, summary, detail rows); `paging.next_offset` is set when more detail rows remain.Reads text others write1 finding
Why it is in this group
- The name "phppos_run_report" says "run": a word for a change.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Findings
- Warn
The server marks "phppos_run_report" read-only (readOnlyHint: true), and its own name, description or input give the class "write".
What this check looks forMatched text
annotations: {"readOnlyHint":true,"destructiveHint":false,"openWorldHint":true}; The name "phppos_run_report" says "run": a word for a change.
Description, as the server wrote it Run one of the store's reports and return it (title, summary, detail rows); `paging.next_offset` is set when more detail rows remain. Report keys and their inputs come from phppos_list_reports (for example summary_sales, top_sellers, inventory_low, summary_profit_and_loss, summary_taxes, closeout). Typical inputs go in `params`: start_date, end_date, sale_type, location_ids (array), category_id, supplier_id, customer_id, employee_id. A scoped key needs the Reports module plus that report's view permission. GET /reports/{report_key}.
Annotations the server declares
- title: Run report
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
Only reads 20Show 20 read-only tools
phppos_get_customerOne customer by person id: contact details, tier, tax settings, balance, credit limit, points, notes and custom fields.Reads private dataReads text others writeNo findings
Why it is in this group
- The name "phppos_get_customer" says "get": a word for reading.
What it can reach
- private-dataThe description's first sentence says "contact": it reads contacts.
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it One customer by person id: contact details, tier, tax settings, balance, credit limit, points, notes and custom fields. GET /customers/{person_id}.
Annotations the server declares
- title: Get customer
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_get_gift_cardOne gift card by its card number (or id): remaining value, customer and status.Reads text others writeNo findings
Why it is in this group
- The name "phppos_get_gift_card" says "get": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it One gift card by its card number (or id): remaining value, customer and status. GET /giftcards/{giftcard_number}.
Annotations the server declares
- title: Get gift card
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_get_itemOne inventory item by id: prices, tax settings, category, supplier, tags, attributes, variations, tier pricing and per-location settings.Reads text others writeNo findings
Why it is in this group
- The name "phppos_get_item" says "get": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it One inventory item by id: prices, tax settings, category, supplier, tags, attributes, variations, tier pricing and per-location settings. GET /items/{id}.
Annotations the server declares
- title: Get item
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_get_receivingOne receiving by id: supplier, items, quantities, costs and payments.Reads text others writeNo findings
Why it is in this group
- The name "phppos_get_receiving" says "get": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it One receiving by id: supplier, items, quantities, costs and payments. GET /receivings/{id}.
Annotations the server declares
- title: Get receiving
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_get_saleOne sale by id with line items, payments, taxes, customer and employee (verbosity full by default).Reads text others writeNo findings
Why it is in this group
- The name "phppos_get_sale" says "get": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it One sale by id with line items, payments, taxes, customer and employee (verbosity full by default). GET /sales/{id}.
Annotations the server declares
- title: Get sale
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_get_supplierOne supplier by person id.Reads text others writeNo findings
Why it is in this group
- The name "phppos_get_supplier" says "get": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it One supplier by person id. GET /suppliers/{person_id}.
Annotations the server declares
- title: Get supplier
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_list_appointmentsList appointments (bookings) with customer, employee, service, start and end time, optionally within a time window.Reads text others writeNo findings
Why it is in this group
- The name "phppos_list_appointments" says "list": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it List appointments (bookings) with customer, employee, service, start and end time, optionally within a time window. GET /appointments.
Annotations the server declares
- title: List appointments
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_list_categoriesList item categories with their ids.Reads text others writeNo findings
Why it is in this group
- The name "phppos_list_categories" says "list": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it List item categories with their ids. Use the ids to filter items or to file a new item. GET /categories.
Annotations the server declares
- title: List categories
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_list_customersList or search customers with contact details, tier, store-account balance, credit limit and loyalty points.Reads private dataReads text others writeNo findings
Why it is in this group
- The name "phppos_list_customers" says "list": a word for reading.
What it can reach
- private-dataThe description's first sentence says "list" and "contact": it reads contacts.
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it List or search customers with contact details, tier, store-account balance, credit limit and loyalty points. Search by text or by one field (email, phone_number, first_name, last_name, account_number). GET /customers.
Annotations the server declares
- title: List customers
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_list_employeesList employees with name, contact details, username, hire date, manager, commission and pay rate settings and assigned locations.Reads private dataReads text others writeNo findings
Why it is in this group
- The name "phppos_list_employees" says "list": a word for reading.
What it can reach
- private-dataThe description's first sentence says "list" and "contact": it reads contacts.
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it List employees with name, contact details, username, hire date, manager, commission and pay rate settings and assigned locations. Passwords and the permission maps are never returned. GET /employees.
Annotations the server declares
- title: List employees
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_list_expensesList recorded expenses with type, description, date, amount, tax, payment type, category and location.Reads text others writeNo findings
Why it is in this group
- The name "phppos_list_expenses" says "list": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it List recorded expenses with type, description, date, amount, tax, payment type, category and location. GET /expenses.
Annotations the server declares
- title: List expenses
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_list_gift_cardsList gift cards with number, description, remaining value, customer and whether inactive.Reads text others writeNo findings
Why it is in this group
- The name "phppos_list_gift_cards" says "list": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it List gift cards with number, description, remaining value, customer and whether inactive. GET /giftcards.
Annotations the server declares
- title: List gift cards
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_list_invoicesList customer invoices (money customers owe) or supplier invoices (money the store owes) with date, due date, status and amount.Reads text others writeNo findings
Why it is in this group
- The name "phppos_list_invoices" says "list": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it List customer invoices (money customers owe) or supplier invoices (money the store owes) with date, due date, status and amount. GET /invoices/customer or /invoices/supplier.
Annotations the server declares
- title: List invoices
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_list_item_kitsList item kits (bundles of items sold together) with their prices.Reads text others writeNo findings
Why it is in this group
- The name "phppos_list_item_kits" says "list": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it List item kits (bundles of items sold together) with their prices. GET /item_kits.
Annotations the server declares
- title: List item kits
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_list_itemsList or search inventory items with name, item number, category, supplier, prices and reorder level.Reads text others writeNo findings
Why it is in this group
- The name "phppos_list_items" says "list": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it List or search inventory items with name, item number, category, supplier, prices and reorder level. Search by text, or by one field (name, item_number, product_id, supplier, tag_name...). GET /items.
Annotations the server declares
- title: List items
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_list_locationsList the store's locations (shops/warehouses) with name, address, phone, email, time zone and default tax rates, plus each location's registers (id and name).Reads private dataReads text others write1 finding
Why it is in this group
- The name "phppos_list_locations" says "list": a word for reading.
What it can reach
- private-dataThe description's first sentence says "list" and "email": it reads mail.
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
- untrusted-inputThe description's first sentence says "list" and "email": it reads inbound email, which other people can write.
Findings
- Info
The description mentions "credentials".
What this check looks forMatched text
description: "...ustomers and reports. Payment-processor credentials and device settings are never returned...."
Description, as the server wrote it List the store's locations (shops/warehouses) with name, address, phone, email, time zone and default tax rates, plus each location's registers (id and name). Use the location ids to filter sales, expenses, customers and reports. Payment-processor credentials and device settings are never returned. GET /locations.
Annotations the server declares
- title: List locations
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_list_receivingsList receivings (stock received from suppliers, purchase orders, transfers) with supplier, totals and items, by date range.Reads text others writeNo findings
Why it is in this group
- The name "phppos_list_receivings" says "list": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it List receivings (stock received from suppliers, purchase orders, transfers) with supplier, totals and items, by date range. GET /receivings.
Annotations the server declares
- title: List receivings
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_list_reportsThe catalog of the store's reports (138 of them: sales summaries, top sellers, inventory low/aging/summary, profit and loss, taxes, payments, employee, customer, supplier and store…Reads text others writeNo findings
Why it is in this group
- The name "phppos_list_reports" says "list": a word for reading.
What it can reach
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it The catalog of the store's reports (138 of them: sales summaries, top sellers, inventory low/aging/summary, profit and loss, taxes, payments, employee, customer, supplier and store-account reports) with the inputs each accepts. Without `search` only the report keys are returned; with `search` (for example 'inventory' or 'profit') the matching reports are returned with their inputs. GET /reports.
Annotations the server declares
- title: List reports
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_list_salesList or search completed sales, by date range, customer (id or email) or location.Reads private dataReads text others writeNo findings
Why it is in this group
- The name "phppos_list_sales" says "list": a word for reading.
What it can reach
- private-dataThe description's first sentence says "list" and "email": it reads mail.
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
- untrusted-inputThe description's first sentence says "list" and "email": it reads inbound email, which other people can write.
Description, as the server wrote it List or search completed sales, by date range, customer (id or email) or location. verbosity: minimal (headline fields), medium (adds customer, totals, profit, location - the default here) or full (every line item, payment and tax). Suspended sales (layaways, estimates) are fetched with suspended_type. GET /sales.
Annotations the server declares
- title: List sales
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
phppos_list_suppliersList or search suppliers with contact details, company, account number and balance.Reads private dataReads text others writeNo findings
Why it is in this group
- The name "phppos_list_suppliers" says "list": a word for reading.
What it can reach
- private-dataThe description's first sentence says "list" and "contact": it reads contacts.
- untrusted-inputThe server marks it openWorldHint: true: it reaches things outside the server's own data.
Description, as the server wrote it List or search suppliers with contact details, company, account number and balance. GET /suppliers.
Annotations the server declares
- title: List suppliers
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: true
This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.
Exfil surface
Which tools read private data, which read text someone else can write, and which can send data out. One of each is a path a prompt injection can use.
No private-data, untrusted-input, outbound path in this server alone: no tool is tagged outbound.
- Reads private data6
- Reads files, mail, messages, databases, secrets, calendars or repositories.
- Reads text others write26
- Brings in text someone else can write: web pages, inbound email, messages, issues and comments.
- Can send data out0
- Can carry data to people or systems: it sends, posts or publishes, or takes a recipient, channel or URL.
Other servers in the same agent add their own tools to these paths. Audit your whole setup to see them together.
Findings
Matches of fixed checks, with the text they matched.
The server marks "phppos_run_report" read-only (readOnlyHint: true), and its own name, description or input give the class "write".
What this check looks forMatched text
annotations: {"readOnlyHint":true,"destructiveHint":false,"openWorldHint":true}; The name "phppos_run_report" says "run": a word for a change.
The description mentions "credentials".
What this check looks forMatched text
description: "...ustomers and reports. Payment-processor credentials and device settings are never returned...."
History
Changes to its tool definitions and to its remote endpoint, newest first.
No change seen yet. Its tools are rescanned every day, and a remote endpoint is looked at once a week.
Install
Pinned to version 1.1.0. Values in angle brackets are yours to fill in.
claude mcp add --transport http php-point-of-sale https://php-point-of-sale.usefulapi.io/mcpclaude mcp add --transport http php-point-of-sale https://php-point-of-sale.usefulapi.io/mcpRun in a terminal.
Claude Code permissions
Allow the reads, ask before a change or a way out, deny the deletes. Paste into .claude/settings.json.
{
"permissions": {
"allow": [
"mcp__php-point-of-sale__phppos_list_locations",
"mcp__php-point-of-sale__phppos_list_items",
"mcp__php-point-of-sale__phppos_get_item",
"mcp__php-point-of-sale__phppos_list_categories",
"mcp__php-point-of-sale__phppos_list_item_kits",
"mcp__php-point-of-sale__phppos_list_sales",
"mcp__php-point-of-sale__phppos_get_sale",
"mcp__php-point-of-sale__phppos_list_receivings",
"mcp__php-point-of-sale__phppos_get_receiving",
"mcp__php-point-of-sale__phppos_list_customers",
"mcp__php-point-of-sale__phppos_get_customer",
"mcp__php-point-of-sale__phppos_list_suppliers",
"mcp__php-point-of-sale__phppos_get_supplier",
"mcp__php-point-of-sale__phppos_list_employees",
"mcp__php-point-of-sale__phppos_list_invoices",
"mcp__php-point-of-sale__phppos_list_expenses",
"mcp__php-point-of-sale__phppos_list_gift_cards",
"mcp__php-point-of-sale__phppos_get_gift_card",
"mcp__php-point-of-sale__phppos_list_appointments",
"mcp__php-point-of-sale__phppos_list_reports"
],
"ask": [
"mcp__php-point-of-sale__phppos_run_report"
],
"deny": [
"mcp__php-point-of-sale__phppos_create_customer",
"mcp__php-point-of-sale__phppos_update_customer",
"mcp__php-point-of-sale__phppos_create_item",
"mcp__php-point-of-sale__phppos_update_item",
"mcp__php-point-of-sale__phppos_create_expense"
]
}
}Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. A read that can send data out (it takes a URL, say) asks first too. It assumes the server is installed as php-point-of-sale. Review it before you use it.
Capability tags behind 26 rules
- mcp__php-point-of-sale__phppos_list_locations private-data, untrusted-input
- mcp__php-point-of-sale__phppos_list_items untrusted-input
- mcp__php-point-of-sale__phppos_get_item untrusted-input
- mcp__php-point-of-sale__phppos_list_categories untrusted-input
- mcp__php-point-of-sale__phppos_list_item_kits untrusted-input
- mcp__php-point-of-sale__phppos_list_sales private-data, untrusted-input
- mcp__php-point-of-sale__phppos_get_sale untrusted-input
- mcp__php-point-of-sale__phppos_list_receivings untrusted-input
- mcp__php-point-of-sale__phppos_get_receiving untrusted-input
- mcp__php-point-of-sale__phppos_list_customers private-data, untrusted-input
- mcp__php-point-of-sale__phppos_get_customer private-data, untrusted-input
- mcp__php-point-of-sale__phppos_list_suppliers private-data, untrusted-input
- mcp__php-point-of-sale__phppos_get_supplier untrusted-input
- mcp__php-point-of-sale__phppos_list_employees private-data, untrusted-input
- mcp__php-point-of-sale__phppos_list_invoices untrusted-input
- mcp__php-point-of-sale__phppos_list_expenses untrusted-input
- mcp__php-point-of-sale__phppos_list_gift_cards untrusted-input
- mcp__php-point-of-sale__phppos_get_gift_card untrusted-input
- mcp__php-point-of-sale__phppos_list_appointments untrusted-input
- mcp__php-point-of-sale__phppos_list_reports untrusted-input
- mcp__php-point-of-sale__phppos_run_report untrusted-input
- mcp__php-point-of-sale__phppos_create_customer untrusted-input
- mcp__php-point-of-sale__phppos_update_customer untrusted-input
- mcp__php-point-of-sale__phppos_create_item untrusted-input
- mcp__php-point-of-sale__phppos_update_item untrusted-input
- mcp__php-point-of-sale__phppos_create_expense untrusted-input
Pin
Keep the decision: fail CI when the tools change, follow every change, or show a badge.
Pin in CI
Fail a build when the tools you reviewed are not the tools the server serves today.
curl -s "https://anlyon.dev/api/v1/servers/io.usefulapi/php-point-of-sale/verify?hash=0283d259e6a8f8650578aac4cacb6c370f956cca950134c6c3f16345d9717caa" | jq -e '.changed == false'Pinned hash 0283d259e6a8, from Oct 24, 2026, 12:18 UTC.
Watch
Get told when its tools change: a new tool, a new description, a new class.
https://anlyon.dev/servers/io.usefulapi/php-point-of-sale/changes.xmlAn Atom feed. Works in any feed reader or Slack's RSS app.
Badge
[](https://anlyon.dev/servers/io.usefulapi/php-point-of-sale)Source: MCP Registry · repository. Synced Oct 24, 2026, 13:18 UTC.