AI agents & MCP
Connect an AI coding agent (Claude Code or Codex) to your workspace and operate it in natural language: read and write records, run app workflows, and edit the website. Your workspace runs a built-in MCP server (Model Context Protocol), so there is nothing to host and no integration to build. The agent acts as one workspace user, every call is bounded by that user's permissions, and the server records what it does.
Availability
The MCP server is enabled per workspace, on request — it is not installed
automatically when a workspace is created, on any plan, so /mcp will 404
until we switch it on. Email company@everjust.co
to have it enabled. It is included at no extra charge on the With Agents
and New Business licenses.
Connect an agent
The quickest path is the one-click button in your profile. It mints a key for the account you are signed in as and shows a ready-to-paste config once.
- Open Profile Settings from the top-right avatar menu.
- Go to the API & AI Agent tab.
- Click Connect an AI agent and re-enter your password when prompted.
- Copy one of the configs shown — MCP JSON, Claude Code, or Codex. The key is shown once and is valid for one year.
- Paste it into your agent and start a session. Ask the agent to run
platform_infofirst.
The agent acts with the permissions of whoever minted the key. For anything beyond a person driving their own account, give the agent its own scoped user instead.
Connect manually
If you would rather wire it up by hand, mint a key for the target user (Profile Settings → API & AI Agent → New API Key, or Account Security → New API Key on workspaces without agents enabled), then add the server:
Claude Code
claude mcp add --transport http --scope user everjust \
https://<workspace>.everjust.app/mcp \
--header "Authorization: Bearer YOUR_API_KEY"
Codex (~/.codex/config.toml)
[mcp_servers.everjust]
url = "https://<workspace>.everjust.app/mcp"
bearer_token_env_var = "EVERJUST_API_KEY"
One connection maps to one workspace. To work across two workspaces, register two servers with distinct names and their own keys:
claude mcp add --transport http --scope user everjust-acme \
https://acme.everjust.app/mcp --header "Authorization: Bearer ACME_KEY"
claude mcp add --transport http --scope user everjust-globex \
https://globex.everjust.app/mcp --header "Authorization: Bearer GLOBEX_KEY"
Once connected, the tools appear to the agent namespaced by server — for
example mcp__everjust__search. List and remove connections with
claude mcp list and claude mcp remove everjust.
Check the connection
There are two ways to authenticate, and a browser sign-in is the expected one:
- Sign in (preferred). Point a current MCP client at the URL with no
credential. It receives a
401carryingresource_metadata, discovers your workspace's authorization server, and opens a browser for you to sign in and approve the agent. You never paste a key. Each agent can be revoked on its own from My Profile → API & AI Agent → Connected agents. - A static API key. Unchanged and not deprecated — it is what headless and CI clients use, where no browser exists to complete a sign-in.
If your agent opens a consent screen, that is the sign-in path working. To confirm the endpoint and a key by hand:
curl -X POST https://acme.everjust.app/mcp \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize",
"params":{"protocolVersion":"2025-06-18"}}'
That is the initialize handshake, which every client in the field uses today
and which keeps working unchanged. A 200 with result.serverInfo and an
instructions block means the server is up and the key is valid. A 401 means
a bad key or URL. A GET to /mcp returns 405 by design; the server speaks
stateless JSON over POST, one response per request, and accepts batches of up
to 50 messages.
Protocol versions
The server speaks two eras of MCP on the same URL, and picks between them from how your client opens the conversation. You do not configure this.
| Era | Revisions | How a client opens |
|---|---|---|
| Legacy | 2025-06-18 (default), 2025-03-26, 2024-11-05 |
the initialize handshake |
| Modern | 2026-07-28 |
no handshake — each request carries its own _meta |
If you already have an agent connected, nothing changes. Legacy clients have no way to fall forward to a newer revision, so the handshake stays supported rather than being replaced. Existing Claude Code and Codex configs keep working as they are.
The 2026-07-28 revision drops the handshake and makes the protocol itself
stateless: there is no initialize, no session id, and every request carries
its own protocol version. A modern request puts that version in params._meta
under io.modelcontextprotocol/protocolVersion, and sends two headers the
server checks against the body:
Mcp-Method— must equal the request'smethod.Mcp-Name— required fortools/call,resources/readandprompts/get, and must equal the name or uri inparams.MCP-Protocol-Version— optional, but if you send it, it must match the version in_meta.
Modern results come back with a resultType and the server's identity under
_meta. To ask the server what it speaks, call server/discover — it returns
every supported revision, the server's capabilities, and the same operating
instructions the handshake used to carry:
curl -X POST https://acme.everjust.app/mcp \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Mcp-Method: server/discover" \
-d '{"jsonrpc":"2.0","id":1,"method":"server/discover",
"params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28"}}}'
Two errors are specific to this, both returned with HTTP 400: -32022 means
the revision you asked for is not one the server implements, and its
error.data.supported lists the ones that are; -32020 means a header
contradicts the body, and the message names which one.
What the agent can do
A generic, permission-bounded surface over your data, plus purpose-built tools for live workspace state and the website:
| Tool | Purpose |
|---|---|
search · get · count · find |
Read records and resolve names |
list_models · describe_model |
Discover models and your access to them |
create · update · delete |
Write records (delete needs confirm) |
call |
Call a public model method (e.g. confirm an order, log a note) |
aggregate |
Group and total in the database — the only way past the 500-row read cap |
mailbox_list · inbox_read · inbox_message · mail_send |
Read your mailboxes and send (reading never marks anything read) |
platform_info · list_installed_modules · whats_new · current_time |
Live workspace capabilities and the workspace clock |
module_status · module_install · module_upgrade · module_configure · module_uninstall |
Inspect and change what is installed (administrator only, except module_status) |
website_pages · website_new_page · website_edit_page · website_publish · website_menu · website_redirect |
Manage the website |
See the MCP tool reference for every tool with its parameters
and return shapes. platform_info reports the workspace's version, installed
apps, and the full tool list, so the agent always knows the current
capabilities of this workspace.
How the agent reads and writes your data
A few patterns keep an agent's calls correct on a workspace it hasn't seen before:
- Check access before writing.
describe_modelreturnsyour_access(read/create/write/unlinkbooleans for the connected user). Seeing a model inlist_modelsdoes not mean rows come back — schema is broadly readable, data stays role-bounded. - Resolve names to ids with
find. It runs a fuzzy name search and returns{id, name}pairs, so the agent doesn't guess record ids. - Domains are lists of triples.
[["email", "!=", false]]; use"|"for OR; dotted paths traverse relations ("stage_id.name"). - Relations take the right shape. A many2one field takes an id; one2many and
many2many fields take command tuples —
[[6, 0, [ids]]]to replace,[[4, id]]to add one. deletepreviews first. Adeletewithoutconfirm:truereturnswould_delete: [{id, name}]and changes nothing; the agent re-calls withconfirm:trueto proceed.AccessErrormeans a role limit, not a missing record. If a call is refused, the user needs the right, or the record rule excludes it.
What the server won't let an agent do
The agent acts as one user, so it can do what that user can do and no more. On top of that, the server hard-refuses a set of actions regardless of the user's role, because a leaked key must not be able to take over a workspace:
- No self-escalation. It can't grant the Administrator role. If a write to a user would grant it by any means, the whole change is rolled back and refused.
- No editing security or structural models. The
create/update/deletetools refuse a fixed set of framework models — access rules, record rules, groups, views, menus, scheduled jobs, server actions, mail templates, configuration parameters, and similar. On those modelscallmay run read methods only, and never underscore-prefixed methods. - No password writes. The password fields are never writable; use the password-reset flow.
- Secrets are masked, not readable. On
searchandget, configuration parameters and fields whose name looks like a secret (token, api key, password) come back as"***", and those parameters can't be written. - Safe writes.
deleteand any non-readcallneedconfirm:true. Anupdatetouching more than 100 records needsconfirm:true. - Bounded results. Reads return at most 500 rows; a request carries at most 50 messages; reads omit binary fields unless you name them.
- Full audit. Every tool call is written to the workspace audit log
(
everjust.mcp.log) and kept for 90 days. See Integration & agent users for how to read it.
Edit the website
Website pages are edited through the website_* tools, which apply changes
copy-on-write: your edit forks a workspace-specific copy of the page, so
platform updates never overwrite it and the shipped page stays intact.
To read a page's current markup, list pages with website_pages, take the
page's view_id, then get that record on ir.ui.view asking for the arch
field. Neither website tool returns markup on its own: website_pages returns
urls, names, view ids, and flags; website_edit_page only writes. Reads on
ir.ui.view are allowed; only writes to it are refused, which is why edits go
through website_edit_page. Keep the site's existing utility-class style, and
read the arch before rewriting it.
Some website work is outside the tool set: registering new reusable snippet blocks, changing search-engine index pinging, translating page bodies, or changing which fields a public form accepts. Do those in the website builder, or ask a workspace administrator.
Operating knowledge (skills)
For task-specific guidance on how mail sending is gated, how the CRM and project models fit together, or how to build a page well, install the EVERJUST agent skills into your coding agent. Each skill is a short, focused guide the agent loads only when relevant. Ask your workspace administrator for the current skills bundle.
Related
- MCP tool reference — all 30 tools, parameters, and return shapes.
- Integration & agent users — give an agent its own least-privilege account and read its audit trail.
- External API — the JSON and XML-RPC API the MCP server sits on.
Last reviewed: 2026-07-21
Need a hand with this? company@everjust.co — a human answers.