You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 30353cd
Browse filesBrowse the repository at this point in the historyBrowse files
Merge origin/main: combine read-only mode with MCP OAuth AdminForth/1970/please-introduce-same-oauth-au
Keeps both new MCP auth secret columns, read_only from main and
oauth_client_id from this branch, in the dev-demo resource, Prisma schema
and plugin config. The MCP docs describe the read-only checkbox for OAuth
connections and keep the page size, tool timeout and agent guidance
sections.
Copy file name to clipboardExpand all lines: adminforth/documentation/docs/tutorial/03-Customization/12-security.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -296,6 +296,8 @@ So to completely hide the email field from all users apart superadmins, you shou
296
296
297
297
So if you will configure the email column in user resource like this, only superadmin will be able to see emails, and only in the list view.
298
298
299
+
> ☝️ `backendOnly` cannot be set on a primary key column (neither `true` nor a function): frontend needs primary key values to build record links, so AdminForth refuses such config on startup.
300
+
299
301
## Blocking login attempts before credentials check
300
302
301
303
`auth.beforeLoginAttempt` hooks are called on every request to the login endpoint, before AdminForth looks the user up in the database.
Copy file name to clipboardExpand all lines: adminforth/documentation/docs/tutorial/09-Plugins/01-agent.md
+8-22Lines changed: 8 additions & 22 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -668,28 +668,19 @@ To define a custom tool, register an API endpoint with `admin.express.endpoint`.
668
668
669
669
By default, `admin.express.endpoint` applies AdminForth authorization. The endpoint handler receives `adminUser` from the user who is controlling the agent. In other words, all permissions and access rights of the agent are defined by that admin user. At the same time, actions done by the agent are automatically attributed in the audit log to the admin user who is controlling the agent.
670
670
671
-
If a tool is risky, you can attach AdminForth agent metadata directly to the endpoint with the `agent` field.
671
+
You can attach AdminForth agent metadata directly to the endpoint with the `agent` field.
672
672
673
673
```ts
674
-
typeAgentRiskLevel='safe'|'danger';
675
-
676
674
typeAgentToolMeta= {
677
-
riskLevel?:AgentRiskLevel;
678
-
confirmation?: {
679
-
title?:string;
680
-
message?:string;
681
-
confirmLabel?:string;
682
-
};
675
+
requiresHumanApproval?:boolean;
676
+
hiddenFromAgents?:boolean;
677
+
onlyReadsData?:boolean;
683
678
};
684
679
```
685
680
686
-
Use it in `.endpoint(...)` like this:
687
-
688
-
-`riskLevel: 'safe'` marks the tool as low-risk.
689
-
-`riskLevel: 'danger'` marks the tool as dangerous.
690
-
-`confirmation` customizes the confirmation dialog shown before the tool is executed.
691
-
692
-
This metadata is rendered into the generated OpenAPI document, so the agent can understand that a tool is dangerous and requires an explicit confirmation UI before execution.
681
+
-`requiresHumanApproval: true` makes the agent ask the user for approval before it runs the tool. MCP clients receive the `destructiveHint` annotation.
682
+
-`hiddenFromAgents: true` keeps the endpoint out of agent tools, both in the agent and in the [MCP server](/docs/tutorial/Plugins/mcp/). Use it for endpoints that serve your admin panel UI and must not be called by agents.
683
+
-`onlyReadsData: true` declares that the endpoint does not change any data. MCP clients receive the `readOnlyHint` annotation, and a [read-only MCP server](/docs/tutorial/Plugins/mcp/#read-only-mode) exposes only such endpoints.
693
684
694
685
This example uses the same email adapter pattern shown in the Email Invite and Email Password Reset plugins. The transport below uses Mailgun only to keep the snippet short; you can replace it with SES or any other adapter from [List of adapters](/docs/tutorial/ListOfAdapters/).
Copy file name to clipboardExpand all lines: adminforth/documentation/docs/tutorial/09-Plugins/30-mcp.md
+21-1Lines changed: 21 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,6 +8,8 @@ slug: /tutorial/Plugins/mcp
8
8
9
9
The MCP plugin exposes AdminForth API methods as remote MCP tools. An agent connects either through OAuth sign-in, where the user approves it in the browser, or with an auth secret the user creates. Every request runs as that AdminForth user, so the same resource permissions, validation, and hooks apply.
10
10
11
+
Endpoints marked with `agent: { hiddenFromAgents: true }` are not exposed. AdminForth and its plugins mark the endpoints the admin panel uses internally, such as login, two-factor authentication, passkeys, and agent chat. Mark your own endpoints the same way to keep them away from agents.
@@ -131,7 +136,7 @@ The plugin adds **MCP Settings** under the user profile. With OAuth sign-in enab
131
136
132
137
OAuth sign-in is enabled by `oauthClientIdField` together with `adminPanelOrigin`, see [Plugin setup](#plugin-setup).
133
138
134
-
When an agent calls the MCP endpoint without a token, the server answers `401` with a `WWW-Authenticate` header that leads the agent to the OAuth metadata. The agent then opens the browser on the consent page `/mcp-authorize`. If the user is not logged in, AdminForth shows its login page first, including two-factor authentication if it is enabled, and returns to the consent page. After the user clicks **Allow**, the agent gets an access token and a refresh token and the connection appears in **MCP Settings** under the client's name.
139
+
When an agent calls the MCP endpoint without a token, the server answers `401` with a `WWW-Authenticate` header that leads the agent to the OAuth metadata. The agent then opens the browser on the consent page `/mcp-authorize`. If the user is not logged in, AdminForth shows its login page first, including two-factor authentication if it is enabled, and returns to the consent page. The consent page has a **Read only** checkbox, see [Read-only mode](#read-only-mode). After the user clicks **Allow**, the agent gets an access token and a refresh token and the connection appears in **MCP Settings** under the client's name.
135
140
136
141
The plugin is an OAuth 2.1 authorization server for public clients:
137
142
@@ -265,6 +270,21 @@ Tool responses are trimmed to save the agent's context:
265
270
-`get_resource_data` rows leave out columns with `null`, empty array and empty object values, and datetimes come without milliseconds.
266
271
- Tool outputs are serialized as YAML instead of JSON.
267
272
273
+
## Read-only mode
274
+
275
+
A read-only connection lets an agent only read data. Check **Read only** when you create an auth secret in **MCP Settings**, or on the consent page when you connect an agent with OAuth sign-in. The mode is stored in `read_only` and cannot be changed later: create a new auth secret or connect the agent again instead.
276
+
277
+
To make every connection read-only, set `readOnly: true` in the plugin options. The **Read only** checkbox is then hidden, the consent page says that the agent can only read data, and new auth secrets and OAuth connections are stored as read-only, so they stay read-only if you remove the option later:
278
+
279
+
```ts
280
+
newAdminForthMcpPlugin({
281
+
readOnly: true,
282
+
// ...
283
+
}),
284
+
```
285
+
286
+
In read-only mode the server exposes only endpoints marked with `agent: { onlyReadsData: true }`, such as `get_resource`, `get_resource_data`, and `aggregate`. Creating, updating, and deleting records and running actions are not available. To make your own endpoint available in read-only mode, mark it with `onlyReadsData: true`.
287
+
268
288
## Audit attribution
269
289
270
290
To show which agent acted on behalf of a user, add a nullable field to the audit log table:
0 commit comments