Skip to main content
Glama
ajemssolutions

AJEMS MCP Connector

Official

AJEMS MCP Connector

Lets Claude and ChatGPT answer questions about an AJEMS workspace — and optionally create apps, forms and records — without anyone logging into AJEMS.

One deployment serves every tenant. Users sign in with their organisation name and AJEMS secret key.


Files

File

Role

server.js

Config, authentication, HTTP transport, health, shutdown

tools.js

Every tool the AI can call

ajems.js

The only module that talks to the AJEMS API

oauth.js

The OAuth handshake Claude and ChatGPT require

cache.js

Per-tenant caching and upstream concurrency limiting

util.js

Small shared helpers

diagnose.js

11-step end-to-end checker

mock-ajems.js

Fake AJEMS with sample data, for testing without a live workspace


Related MCP server: BackCrew ServiceM8 MCP Server

Quick start

npm install
cp .env.example .env      # set PUBLIC_URL and AJEMS_HOST_TEMPLATE
npm start

Verify against a real workspace:

node diagnose.js https://mcp.ajems.com <organisation> <secret-key>

Or try it with no AJEMS at all:

npm run mock              # terminal 1
# set AJEMS_HOST_TEMPLATE=http://localhost:9090/{org}/json_builder
npm start                 # terminal 2
node diagnose.js http://localhost:8080 testco test-secret-key

See DEPLOY.md for nginx, TLS, pm2 and tuning.


Tools

Read-only by default. Set ALLOW_WRITES=true for the four write tools.

Tool

Shown as

Purpose

list_apps_and_forms

See my apps and forms

Discovery; returns total_apps and total_forms

show_form_fields

See what a form contains

Field keys, labels, types, options, record count

count_records

Count records

An exact number, optionally filtered

find_records

Find records

Records with filters, date range, field selection

summarise_records

Total or average records

sum / avg / min / max, optionally grouped

create_app

Create a new app

update_app

Rename or restyle an app

create_form

Create a new form

Field keys generated automatically

update_form

Change a form's settings

Name, description, external read/write access

add_records

Add records

One or many, bounded concurrency

update_record

Update a record

Only the fields you pass

search

Search everything

Keyword search across forms (ChatGPT)

fetch

Open a search result

Full detail for one result (ChatGPT)

Read-only by default. Set ALLOW_WRITES=true for the six write tools.

Two rules the tools follow

Never make the model count. Every list carries an explicit total, placed first in the response. Models that summarise long lists return numbers that drift between identical questions; count_records exists so a "how many" question never depends on counting an array.

No write happens without confirm: true. The first call returns a preview and a warning instead of writing. For update_record the preview shows current values next to the new ones. This is enforced in the tool, not left to the model's judgement.

summarise_records computes on the server. Without it, "total by city" would pull thousands of rows into the model's context and add them by hand — slow, expensive, and wrong past a certain size.

search and fetch keep those exact names because outside Developer Mode, ChatGPT only calls tools named search and fetch and ignores everything else.


How a question gets answered

Claude asks "how many entries in July, by city?":

  1. list_apps_and_forms → finds the form

  2. show_form_fields → learns that date_1750943312417 is the date field and dropdown_1750943301432 holds cities

  3. summarise_records with a date range and group_by → gets three numbers back

  4. Writes the answer in plain English

Field keys are auto-generated (date_1750943312417), which is why step 2 is not optional. The tool descriptions tell the model this, and it chains the calls itself.


Tenant isolation

  • Tenant comes from the session, resolved server-side from the bearer token

  • No tool schema has a tenant, org or url parameter — nothing exists for a model to be talked into changing

  • ajems.js is the only module issuing outbound requests, and only to that tenant's base URL

  • Cache keys are namespaced by tenant and a hash of the secret key, so tenants can't read each other's cached entries and a rotated key self-expires

  • Organisation names are stripped to subdomain-safe characters, so an entry like evil.com/x can't redirect the server elsewhere

  • Every tool call is logged as JSON with tenant and user

When adding a tool, re-check the second point.


How disconnects are detected (and the honest limitation)

The Connector Store shows a Claude/ChatGPT card as Connected only while this server vouches for it. Three paths take a card down; know which one you are relying on:

1. Client-initiated revocation — instant, but NOT guaranteed. This server implements RFC 7009: it advertises revocation_endpoint in its OAuth metadata and serves POST /revoke. A client that calls it on disconnect gets the exact session invalidated and one status:"disconnected" report sent within seconds. However: nothing obliges claude.ai to call it. Anthropic's connector documentation specifies no signal of any kind on connector removal, the MCP authorization spec does not reference RFC 7009 at all (clients are neither required nor recommended to revoke on disconnect), and in production claude.ai has been observed removing a connector silently. Whether claude.ai caches the OAuth metadata per connector (so a later-added revocation endpoint is only picked up after remove + re-add) is also undocumented. Treat instant detection as best-effort, never as a guarantee.

2. Dashboard Disconnect — instant and always available. Clicking Disconnect on the Store card takes effect immediately and sticks: heartbeats and check-status never resurrect it; only a fresh sign-in (reconnect: true) does. This is the reliable way to take a card down now.

3. Dormancy fallback — guaranteed, within the activity window. lastSeen advances only on genuine authenticated MCP requests. A session with no traffic for CONNECTOR_ACTIVE_WINDOW_MS (default 1 hour) goes dormant: one status:"disconnected" report is sent and heartbeats stop, so a silent claude.ai removal shows as Disconnected within roughly the window plus one heartbeat (~65 minutes at defaults). A dormant session that speaks again reports back the moment it wakes. Shortening the window makes silent removals surface faster, but marks genuinely-connected-but-idle users Disconnected between uses — they reconnect automatically on their next request, at the cost of the card flapping. 1 hour is the compromise.

There is no fourth option: when the client sends nothing and the user clicks nothing, absence of traffic is the only signal, and it is indistinguishable from idleness until the window expires.

References: Anthropic remote-MCP connector docs · MCP authorization spec · RFC 7009


Testing

27 checks pass against the mock covering the tool layer: all 13 tools present with correct annotations, explicit totals, filtered counts, the confirmation gate blocking and then allowing every write, before/after previews, and search totals. An earlier suite covers authentication, tenant isolation, 20 concurrent users and rate limiting.

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

  • A
    license
    B
    quality
    B
    maintenance
    Enables an AI assistant to interact with ServiceM8 via natural language, supporting lookups and optionally creating or updating records, with tiered safety controls.
    36
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to interact with Jurisly workspaces for tasks like drafting invoices, finding hearing dates, and editing documents through natural language.
    Apache 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to directly interact with ERPNext/Frappe business data and operations, including document management, submissions, cancellations, reports, PDF generation, file uploads, and whitelisted method calls, with per-request permission enforcement.
    MIT

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/ajemssolutions/MCP'

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