Setyenv · Docs
  • English
  • Español
  • 中文
  • 日本語
  • العربية
  • Deutsch
  • Français
  • हिन्दी
  • Bahasa Indonesia
  • Italiano
  • Nederlands
  • Português
  • Русский
  • Türkçe

MCP server

The MCP server lets a person use the platform from the AI app they already use — ChatGPT, Claude, Gemini, Cursor or any other client that speaks the Model Context Protocol (MCP). The app works as that person: it sees and changes exactly what their roles allow here, and nothing more. They ask in their own words — "which of my incidents are still open?", "approve the pending purchase request" — and the app does it through the platform.

Turning it on

The server is off until somebody who manages integrations enables it in Administration → MCP Server. The same screen shows the server address to give to the AI app, short connection steps for the common apps, and the AI apps people have connected, with Disconnect for one person or for the whole app.

While it is off, the address answers that the server is disabled, no AI app can register or start a sign-in, and apps already connected stop working until it is on again.

Connecting an AI app

  • ChatGPT, Claude and other apps that support OAuth: add a custom connector (a remote MCP server) with the server address. The app registers itself, sends the person here to sign in, and shows the platform's consent screen; after Authorize it works as that person. Nobody has to create a client by hand.
  • Other MCP clients: add a remote server of type Streamable HTTP with the server address, and authenticate with an API key sent as Authorization: Bearer pfmk_…, or with a WordPress application password over HTTP Basic authentication.

A browser's login cookie is never accepted: the server answers only a credential the app presents itself.

With plain permalinks the server address is /?rest_route=/pfm/v1/mcp. Apps that discover the sign-in by themselves look for it under /.well-known/, which plain permalinks may not serve; switch to pretty permalinks if an app cannot start the sign-in.

What the app can do

ToolWhat it does
whoamiWho the person is: roles, groups, language and what they may do.
list_appsThe applications and modules the person's navigation shows.
list_tablesEvery table the person may read.
describe_tableThe fields the person can see: type, required, read-only, choices, reference target.
query_recordsFilter, sort and page records (EQL), with the total counted by the server.
get_recordOne record by its sys_id.
create_record, update_recordWrite records, validated as the app validates them.
delete_recordDelete a record, only after the person confirms (see below).
list_record_actions, run_record_actionThe record's buttons the person may press.
list_table_actions, run_table_actionThe buttons of a table's list, which run without choosing a record.
get_journal, add_journal_entryComments and work notes.
list_api, call_apiEverything else the person can do in the platform, through its REST API (below).
list_reportsThe reports and dashboards shared with the person.
show_report, show_dashboardA report's figures, or every report of a dashboard, computed as the person.

Values come back as display values in the person's language. Pending approvals are ordinary records: the app finds the person's waiting tasks and decides them with the task's Approve and Reject actions.

Everything else: the platform's API

The rest of what a person can do in the platform — attachments, relations between records, bulk updates, dialogs, the design of tables, fields, forms and navigation, business rules, UI policies, views, roles and groups, translations — goes through the platform's REST API. list_api lists its routes, with their methods and parameters; call_api calls one, as the person. Their roles decide what each call may do, exactly as in the app: a person whose role manages schemas can design a table from the AI app, and a person who only reads records cannot.

The interactive view

AI apps that support MCP Apps — Claude, ChatGPT, VS Code and Goose among them — show a tool's result as an interactive view inside the conversation instead of text: the records as a table, a record laid out like its form, a report or a dashboard drawn as in the app. Other apps keep receiving the same text as always.

Open tasks shown as a table in the conversation

From the view the person can:

  • open a row, sort by a column and load the next page;
  • edit a record — text, numbers, dates, yes/no, choices and references — or create one; a refusal from a business rule shows on the form, with nothing typed lost;
  • read and add comments and work notes, and run the record's actions;
  • confirm a delete or an action that asks to be confirmed with a click, after a summary in their language of what it does;
  • open a report or a dashboard and click a figure to see the records behind it;
  • open anything in the app with Open in Setyenv.

A dashboard drawn in the conversation

The view follows the person's language and the app's light or dark mode. Everything it does is a call to the same tools the model uses, made by the AI app on the person's connection, under the same rules; the view itself never contacts the site. The AI model is told what the person did in the view, so the conversation can go on from there.

A record opened from the conversation

What it cannot do

  • Anything the person cannot do in the app.
  • Reach credentials: OAuth clients and tokens, outbound connections, API keys and the MCP server's own settings are managed in the app, never through MCP.
  • Act as an administrator through OAuth. A token never does, so an administrator account cannot authorize an app: connect with the account of the person who will use it.

Security model

  • Off by default, switched on by somebody who manages integrations.
  • As the person, enforced where the app enforces it. Every tool is carried out by the platform's own REST routes, as the person, so table permissions, row visibility, field projection, API-key scope, rate limits and validation apply exactly as they do in the app and the API. The MCP layer has no path of its own to the data.
  • Deletes, destructive actions and forced calls take two calls. A call through the API that deletes, or that passes force to override a data-loss guard, is one of them. The first changes nothing and returns a summary naming the record and what goes with it, plus a confirmation that is single-use, valid for 10 minutes and bound to the person and the exact call. The app shows the summary and asks; only the identical call carrying the confirmation runs.
  • An app that registers itself gets little. It is a public client: no secret, the authorization-code flow with PKCE (S256) only, redirect addresses on https or on the person's own computer (localhost), no client credentials and no service user. Registrations are rate-limited per address, and an app nobody uses for 30 days is removed. The consent screen tells the person that the app's name is its own claim, and where the authorization will be sent.
  • Tokens are bound to the server. A token requested for this MCP server names it (RFC 8707), and the server refuses a token issued for anything else.
  • Browsers are kept out. A request from another site's page (a foreign Origin) is refused, a cookie is not a credential, and the consent screen cannot be framed.
  • Revoking is immediate: Disconnect on the MCP Server screen, or revoke the token in the Tokens table.
  • A ceiling per connection: at most 120 requests a minute for one credential; past it the server answers 429 with Retry-After.
  • The view is sealed. It has no network access and no credential, only its own script may run in it, and every value is shown as text, so nothing stored in a record can execute in it.

For developers

The endpoint is POST /wp-json/pfm/v1/mcp: MCP Streamable HTTP, stateless, JSON responses only, protocol versions 2025-11-25, 2025-06-18, 2025-03-26 and 2024-11-05. Discovery follows the MCP authorization spec: a 401 points at the protected-resource metadata (RFC 9728), which points at the authorization-server metadata (RFC 8414) and its dynamic client registration endpoint (RFC 7591). Filters: pfm_mcp_tools (add tools), pfm_mcp_allowed_origins, pfm_oauth_resources and pfm_oauth_dcr_rate_limit_per_hour.

The ceiling per connection is the filter pfm_mcp_rate_limit_per_minute (0 turns it off). The interactive view follows MCP Apps (SEP-1865, extension io.modelcontextprotocol/ui): one resource, ui://setyenv/app-<version>, of type text/html;profile=mcp-app, listed by resources/list and served by resources/read. Tools with a view carry _meta.ui.resourceUri, and their results carry what the view needs in _meta["setyenv.com/view"], which a model never reads.