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 5de3d8f
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: adminforth/documentation/docs/tutorial/09-Plugins/30-mcp.md
+9-11Lines changed: 9 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -79,7 +79,7 @@ export default {
79
79
80
80
Register `mcpAuthSecrets` in the application's `resources` array.
81
81
82
-
`oauth_client_id` holds the client of an OAuth connection and stays empty for auth secrets. It is needed only for [OAuth sign-in](#oauth-sign-in); without it the plugin works with auth secrets alone. If the table already exists from an earlier plugin version, add only this nullable column with a migration to enable OAuth.
82
+
`oauth_client_id` holds the client of an OAuth connection and stays empty for auth secrets. If the table already exists from an earlier plugin version, add this nullable column with a migration.
83
83
84
84
## Plugin setup
85
85
@@ -110,9 +110,9 @@ new AdminForth({
110
110
});
111
111
```
112
112
113
-
`oauthClientIdField`enables OAuth sign-in. Leave it out to keep only auth secrets, as in plugin versions before OAuth; then the dialog in **MCP Settings** shows only the auth secret form and no OAuth routes are added.
113
+
`oauthClientIdField`and `adminPanelOrigin` are required: [OAuth sign-in](#oauth-sign-in) is always enabled, and auth secrets work alongside it.
114
114
115
-
`adminPanelOrigin` is the public origin agents connect to, such as `https://admin.example.com`, without a path; the plugin appends the AdminForth `baseUrl`. It is required with OAuth sign-in, and the app does not start without it: the OAuth issuer and the MCP resource URL are built from it, and MCP clients reject a resource URL whose origin differs from the one they connected to. The origin is not inferred from request headers. The MCP server also identifies itself to agents by it and by [`customization.brandName`](/docs/tutorial/Customization/branding/), which tells several AdminForth installations apart.
115
+
`adminPanelOrigin` is the public origin agents connect to, such as `https://admin.example.com`, without a path; the plugin appends the AdminForth `baseUrl`. The OAuth issuer and the MCP resource URL are built from it, and MCP clients reject a resource URL whose origin differs from the one they connected to. The origin is not inferred from request headers. The MCP server also identifies itself to agents by it and by [`customization.brandName`](/docs/tutorial/Customization/branding/), which tells several AdminForth installations apart.
116
116
117
117
The MCP endpoint is:
118
118
@@ -124,18 +124,16 @@ If `baseUrl` is configured, it appears before `/adminapi/v1/mcp`.
124
124
125
125
## Connecting an agent
126
126
127
-
The plugin adds **MCP Settings** under the user profile. With OAuth sign-in enabled, **Connect agent** opens a dialog with a tab per client:
127
+
The plugin adds **MCP Settings** under the user profile. **Connect agent** opens a dialog with a tab per client:
128
128
129
129
-**Claude Code** – `claude mcp add --transport http <name> <url>`, then `/mcp` in Claude Code to sign in;
130
130
-**Codex** – `codex mcp add <name> --url <url>`; Codex opens the browser to sign in, or run `codex mcp login <name>`;
131
131
-**Other** – creates an auth secret for clients without OAuth sign-in.
132
132
133
-
`<name>` is `brandName` in lowercase with hyphens. The commands use the address the admin panel is opened at, so open it at its public address. The table below the button lists all connections of the user, auth secrets and OAuth ones, and revokes them. A revoked connection stops working on the agent's next request. Logging out, ending sessions and changing the password do not revoke MCP connections: revoke them in this table.
133
+
`<name>` is `brandName` in lowercase with hyphens. The commands use the MCP endpoint URL built from `adminPanelOrigin`. The table below the button lists all connections of the user, auth secrets and OAuth ones, and revokes them. A revoked connection stops working on the agent's next request. Logging out, ending sessions and changing the password do not revoke MCP connections: revoke them in this table.
134
134
135
135
## OAuth sign-in
136
136
137
-
OAuth sign-in is enabled by `oauthClientIdField` together with `adminPanelOrigin`, see [Plugin setup](#plugin-setup).
138
-
139
137
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.
140
138
141
139
The plugin is an OAuth 2.1 authorization server for public clients:
@@ -162,7 +160,7 @@ MCP clients look for the metadata at the host root first. The AdminForth SPA ans
162
160
163
161
## Auth secrets
164
162
165
-
For clients without OAuth sign-in, create an auth secret in the **Connect agent** dialog, on the **Other** tab when OAuth is enabled, and send it with every request:
163
+
For clients without OAuth sign-in, create an auth secret in the **Connect agent** dialog, on the **Other** tab, and send it with every request:
166
164
167
165
```http
168
166
Authorization: Bearer afmcp_...
@@ -218,7 +216,7 @@ The server fetches `client_id` URLs chosen by whoever starts a sign-in. The plug
218
216
-**`Could not fetch the client metadata document`** – the server could not download the client's `client_id` URL; the reason is in the server log. Check outbound network access, or list the client in `devOAuthClients` in development.
219
217
-**`redirect_uri is not listed in the client metadata document`** – the client signs in with a redirect URI its document does not allow. For clients in `devOAuthClients`, add the redirect URI there.
220
218
-**The agent rejects the server's resource or issuer** – `adminPanelOrigin` differs from the origin the agent connects to, for example `http://` instead of `https://` behind a TLS proxy.
221
-
-**`Authentication required: the MCP auth secret or OAuth access token is missing, invalid or revoked.`** – the first answer to an agent without a token, which starts OAuth. If the agent shows it instead of opening the browser, it does not support OAuth sign-in, or OAuth is not enabled: use an auth secret.
219
+
-**`Authentication required: the MCP auth secret or OAuth access token is missing, invalid or revoked.`** – the first answer to an agent without a token, which starts OAuth. If the agent shows it instead of opening the browser, it does not support OAuth sign-in: use an auth secret.
222
220
223
221
`last_used_at` and `last_used_by_agent` are updated in the background without running resource hooks. Client identity comes from per-request `io.modelcontextprotocol/clientInfo` metadata in MCP `2026-07-28`, with legacy `initialize` and `User-Agent` fallbacks.
224
222
@@ -272,9 +270,9 @@ Tool responses are trimmed to save the agent's context:
272
270
273
271
## Read-only mode
274
272
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.
273
+
A read-only connection lets an agent only read data. **Read only**is checked by default when you create an auth secret in **MCP Settings** and 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
274
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:
275
+
To make every connection read-only, set `readOnly: true` in the plugin options. The **Read only** checkbox then stays checked and locked, 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:
0 commit comments