PriorityMCP
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@PriorityMCPFind the screen for open customer invoices and list the 10 largest by amount."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
PriorityMCP
An MCP server over a live Priority ERP installation. It gives an LLM the tools to find the right screen, learn what its columns mean, and query it — rather than a hard-coded method per business question.
Ten tools over Priority's OData v4 API, plus a second channel through
priority-web-sdk for running Priority programs. Serves both transports: stdio for a
local client, and Streamable HTTP over TLS so clients on other machines can connect.
Why discovery rather than a method per domain
The first version of this server had one curated tool, get_sales, built on a
hand-coded map of four invoice screens. Building that map required guessing what each
screen meant, and one of the guesses was wrong: CINVOICES was coded as "credit
invoices" and its amounts multiplied by -1.
EFORM.TITLE on the server says חשבוניות מרכזות — consolidated invoices. Credit
invoices are a different screen entirely (SALECREDITINVOICES, table CUSTSALES),
and on that installation it is not exposed to the API at all. Every total produced
from that mapping was wrong, and nothing in the output looked wrong. The database had
held the correct answer the whole time, in a table nobody had queried.
So the design rule here is: the model asks Priority what things are. Screen names
are opaque English codes whose meaning lives in a Hebrew title, and inferring one from
the other is exactly the mistake to prevent. get_sales still exists but is hidden by
default (PRIORITY_ENABLE_GET_SALES=1 to expose it) — when it is available the model
reaches for it and never exercises discovery.
Related MCP server: MCP Server for Odoo
Quick start
Requires Node 20+. There is no build step: tsx runs the TypeScript directly, so
the code in src/ is the code that runs.
npm install
copy .env.example .env # then fill it in -- every field is documented in place
npm run probe # verifies the connection and what Priority exposes
npm run server # stdio, for a local MCP clientTo serve other machines:
powershell -ExecutionPolicy Bypass -File scripts/make-cert.ps1 # prints the two .env lines
npm run server:http # HTTPS on :3401
powershell -File scripts/client-kit.ps1 # a folder to hand to each clientAs a Windows service (WinSW), so it survives logout and reboot:
.\service\install-service.ps1 # as AdministratorThe service runs src/http.ts from this directory, so deploying a change is
Restart-Service PriorityMCP — no reinstall. Reinstall only when
service/priority-mcp.xml itself changes. Run npm run typecheck before restarting:
the service retries three times on failure and then stays down, so one syntax error is
an outage.
The tools
Tool | What it is for |
| Find a screen from a business concept, in Hebrew or English. Searches an in-memory dictionary; start here. |
| Columns with Hebrew titles, keys, types, sub-forms, screen help, and which table each column reads from. |
| Priority's own help for a screen (F), report (R), procedure (P) or menu (M) — or for one column. Each kind is read from its own generator screen, so the type matters. The way to learn what a program DOES before running it. A permission refusal, an absent record and a wrong name are reported as three different things. |
| Read rows. |
| Totals, counts and "per X". Computed server-side here, by paging — see the |
| The distinct values a code column actually holds, with counts. Use before filtering on one. |
| The configured companies with their real names from the |
| Switch the session's company. Changes the data only. |
| Where the glossary, examples and dictionary have gaps. |
| The documented programs ( |
| Run one to completion, through the Web SDK. Called without inputs it returns the whole dialog Priority would show a person: each parameter's help, type, format, max length, remembered default and lookup source, plus the operator list. Stops with |
| The same programs as an interactive session: |
| AI skills written inside Priority ( |
Clients also receive ~3,100 characters of server-level instructions on initialize
(the discovery order, case sensitivity, never summing currencies, how reversals work).
You do not need to write a system prompt for this.
What was measured about this Priority server
These are findings from the live installation, not documentation. Each one shapes the code, and several are silent failures — the reason the tools do not simply forward OData:
Behaviour | Consequence |
| Paging uses |
|
|
| Counts come from paging, not from asking. |
No | Paging is driven by |
| Filters use chained |
A |
|
| The parent |
URL length limits at roughly 50 | Filters are chunked. |
The service document takes ~70 s | Metadata calls get their own 180 s budget, separate from the 45 s query budget. |
Screen and column names are case-sensitive, and ten pairs differ only by case ( | Names are never case-folded, anywhere. |
Help lives under each kind's own generator screen, all keyed | Reading every kind through |
On a help sub-form path the statuses are inverted: an entity that exists with no help row answers 404, a name that does not exist answers 200 with zero rows | A 404 is read as "none recorded" (an answer), and the name is checked against the dictionary to tell that apart from a wrong name. |
| A negative result from an |
An input step carries far more than the field names: | All of it is forwarded, so a model can explain a parameter and find a legal value with the read tools instead of guessing. A password default is never echoed. |
Priority also remembers the OPERATOR from the previous run, and it is not reset | A supplied value sends operator 0 ( |
A program's | Both go through the same cleaner as screen help before reaching the model. |
A lookup names a TABLE, and a table is not always an entity set: | Each field's lookup is resolved to a readable SCREEN plus the query to list it, so the model can offer real values instead of inventing one for a mandatory field. |
Priority reports an empty report as a message of type error ( | A run that produced nothing is marked |
An output step carries | The formats are forwarded with their titles and |
| Documents support |
| A program with one format skips the dialog, so the multi-format path is pinned offline against the SDK's typed contract rather than live. |
Priority reports an empty report as a message of type | A run whose messages say only that is corrected to |
On Priority's cloud a username and password are refused for OData (401); only a PAT or OAuth is accepted |
|
| It is the source for searching programs, since |
| Skills exist as a feature; reading them needs the screen opened for the API or the API user given the "תחזוקת מערכת" module. |
On Priority's cloud the Web SDK URL is |
|
The cloud web UI itself authenticates with OIDC ( | Per-caller identities on the cloud are PATs ( |
A self-hosted installation's OData certificate is typically self-signed, and Node does not read the Windows trust store — so a certificate the whole domain trusts still fails there. Measured 2026-09-04 on | Pinning the server's own certificate is the answer for a self-signed one, as |
On a self-hosted installation | The 400 is a permission as often as a screen flag, and the two are indistinguishable in the response. Without |
|
|
The dictionary comes from EFORM (~5,800 forms) and is cached on disk for 24 hours,
keyed per installation and shared across companies — screen definitions live at the
tabula.ini level, so every company on one installation has the same dictionary.
Configuration
Everything is in .env, and every setting is documented where it is defined —
see .env.example. The three that decide the shape of a deployment:
PRIORITY_ODATA_URL+PRIORITY_ENVIRONMENTS— end the URL at thetabula.iniand list companies to let callers choose one; end it with a company name for a single-company server. The list is an allowlist, not a hint: the name goes into a URL path, so anything unlisted is refused.PRIORITY_AUTH_MODE—shared(one identity from.env),headers(each caller supplies its own), orelicit(the client asks its user). Header and elicited credentials never enter the model's context, which is why there is nologin()tool.PRIORITY_HOSTING—cloudorself-hosted; detected from the host name when empty and stated in the startup log. It decides how the Web SDK is reached (https://<host>/wcf/service.svcon the cloud, the host root elsewhere) and which identity is tried first (PAT on the cloud, the named user elsewhere). Pin it when one.envserves several installations.PRIORITY_READ_ONLY—1removesrun_program, leaving no way to change anything. Discovery and read tools are never gated: without them a model cannot learn a screen name and goes back to inferring one, which is the failure above.PRIORITY_ALLOW_ALL_PROGRAMS—0(default) allows only the catalogued programs.1allows any of the installation's ~9,200 procedures and reports, withPRIORITY_PROGRAMS_DENYas the exception list. Opening it hands the model programs that post, delete and upgrade, so what still holds is worth knowing: an unknown name is refused against the dictionary rather than sent, a name that is bothPandRis refused until the type is given, an uncatalogued program comes back with acaution, the first call without inputs only reports parameters, and a choice is never made server-side.PRIORITY_MAX_ROWS_PER_QUERYand friends — the ceilings on one call's result, all four taking0to mean no ceiling. Two of them (ROWS_PER_QUERY,RESPONSE_CHARS) bound what lands in the model's context, and raising those does not let a model handle more data — it lets one reply crowd out the conversation. The other two (SCAN_ROWS,GROUPS) bound whataggregatereads while paging, which costs requests and no context at all, and that is the pair to raise when an answer needs more data behind it.
MCP_AUTH_TOKEN is required whenever the listener is not loopback-only. The server
refuses to start without it rather than warning — it holds Priority credentials and
every tool reads live ERP data.
Connecting a client
{
"mcpServers": {
"priority": {
"type": "http",
"url": "https://<server>:3401/mcp",
"headers": {
"X-Priority-User": "...",
"X-Priority-Pass": "...",
"X-Priority-Company": "demo"
}
}
}
}Or Authorization: Bearer <MCP_AUTH_TOKEN> to use the server's own identity. Header
credentials require TLS and are refused over plain HTTP. scripts/client-kit.ps1
packages the CA and these templates into a folder to hand to each client machine.
On Windows, verifying with curl needs --ssl-revoke-best-effort: curl there uses
schannel, which requires a revocation source, and a private CA publishes no CRL. The
flag relaxes the revocation check only. Node-based clients do not need it.
Verify with curl, not with Invoke-WebRequest. Measured 2026-09-04 against a
running listener: a raw SslStream handshakes with it happily — TLS 1.3, AES256 —
and Invoke-WebRequest against the same URL fails with The underlying connection was closed: An unexpected error occurred on a send, under forced TLS 1.2 and under
SystemDefault alike, with certificate validation bypassed either way. The .NET
Framework HTTP stack does not get along with this Node listener. Nothing is wrong
with the server or the certificate when that happens, and both install-ca.ps1 and
the bootstrap's health check used to report a working server as unreachable because
of it — both now use curl, which answers correctly.
Tests
npm run typecheck
npm test # 16 offline suites -- no server, no Priority
npm run test:live # 15 suites against the real installation
npx tsx tests/live.http.ts # the HTTP transport, as a remote client
npx tsx tests/live.headerauth.ts # all four accepted and four refused auth pathsLive tests need NODE_EXTRA_CA_CERTS=<repo>\certs\mcp-ca.pem when TLS is on.
A live suite that cannot reach a resource skips with a stated reason rather than passing quietly — a Priority permission that is closed must not read as a green test.
Deploying to another server
The repository is the whole application: there is no build, so a clone plus
npm ci is a running server. Four things are deliberately not in git and have
to exist on the new machine.
git clone https://github.com/<you>/PriorityMCP.git
cd PriorityMCP
npm ci # package-lock.json pins what this was verified against
copy .env.example .env # then fill it in -- every setting is documented in place
npm run probe # first proof: credentials and connectivityNot in git | What to do on the new server | Why it is excluded |
| Copy | Holds the PAT, the password and the bearer token. |
|
| The certificate names the machine it was made on; another server's name and IP are not in it, so a copied one fails host verification. |
| Download WinSW ( | A third-party binary; |
|
| 336 MB. |
Everything else regenerates: the dictionary cache refetches on first use (~20 s),
client-kit/ comes from scripts/client-kit.ps1, and service/logs/ is created by
the service.
Then install it as a service, exactly as above. service/priority-mcp.xml needs no
editing — its paths use WinSW's %BASE%, so they follow the checkout. The one line
to check is <executable>: it points at C:\Program Files\nodejs\node.exe, the
default install location.
Per-installation settings worth a second look before starting: PRIORITY_HOSTING,
PRIORITY_ODATA_URL + PRIORITY_ENVIRONMENTS, PRIORITY_READ_ONLY, and a new
MCP_AUTH_TOKEN — a token shared between two servers means one leak exposes both.
Layout
src/
server.ts tool registration, the model-facing instructions
http.ts Streamable HTTP transport, TLS, sessions, authentication
odata.ts the Priority OData client, EDMX parsing, the quirks above
dictionary.ts the EFORM screen dictionary, cache, Hebrew search
discovery.ts search_screens / describe_screen / query / column sources
aggregate.ts grouping and totals, computed here
companies.ts per-company context over one shared dictionary
auth.ts shared / headers / elicit
help.ts screen help from EXEC/FORMHELP, HTML and {XXXX.T} references
programs.ts the priority-web-sdk channel
service/ WinSW wrapper, install / uninstall
scripts/ make-cert.ps1, client-kit.ps1
tests/ *.test.ts offline, live.*.ts against the installationnode_modules is not in git (336 MB); package-lock.json is, so npm install
restores what this was verified against. certs/, .env and
service/priority-mcp.exe are also excluded — the repo alone does not reinstall the
service.
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.
This server cannot be installed
Maintenance
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
- PriorifyOAuthapp.priorify
Agent-complete, permission-scoped product operations for Priorify workspaces.
Gateway between LLM agents and world data through eight tools and a bundled endpoint catalog.
List datasets, schemas, run APL queries, and use prompts for exploration, anomalies, and monitoring.
- StackOneOAuthcom.stackone
Give AI agents 30,000+ safe, token-optimized actions across Workday, SAP, Oracle + hundreds more.
Related MCP Servers
- -licenseNot gradedqualityNot gradedmaintenanceEnables AI assistants to interact with Odoo ERP systems through natural language to search records, create entries, update data, and manage business operations. Supports secure authentication and configurable access controls for production environments.-
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to interact with Odoo ERP systems through natural language, allowing users to search, create, update, and manage business records like customers, products, and invoices across any Odoo instance.1Mozilla Public 2.0
- AlicenseAqualityCmaintenanceEnables AI agents to interact with Odoo ERP as the authenticated user, with tools for discovery, planning, and mutations bounded by user permissions.34672MIT
- FlicenseAqualityCmaintenanceEnables interaction with SAP S/4HANA systems via OData, allowing service discovery, metadata exploration, field value retrieval, and CRUD operations through natural language.45-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/YaronMedatech/PriorityMCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server