diff --git a/docs/en/images/openiddict-client-credentials-application.png b/docs/en/images/openiddict-client-credentials-application.png new file mode 100644 index 0000000000..fdcf4a2e5b Binary files /dev/null and b/docs/en/images/openiddict-client-credentials-application.png differ diff --git a/docs/en/low-code/designer.md b/docs/en/low-code/designer.md index ba24034906..9ef7637e5b 100644 --- a/docs/en/low-code/designer.md +++ b/docs/en/low-code/designer.md @@ -165,7 +165,7 @@ Use **Health** before shipping changes. It helps catch missing display propertie ## MCP Integration -The Designer and the low-code MCP surface overlap when the selected layer is **Runtime JSON**, but they are not the same editing surface. The Designer can inspect source-controlled and runtime layers, while [MCP Integration](mcp.md) is intentionally runtime-only and targets the database-backed model. Use the Designer when you want interactive editing and visual feedback. Use MCP when an agent or script needs a structured read, validate, apply, and health-check workflow against the runtime model. +The Designer and the low-code MCP surface overlap when the selected layer is **Runtime JSON**, but they are not the same editing surface. The Designer can inspect source-controlled and runtime layers, while [MCP Integration](mcp.md) is a remote HTTP MCP endpoint that is intentionally runtime-only and targets the database-backed model. Use the Designer when you want interactive editing and visual feedback. Use MCP when an authenticated agent or script needs repeatable runtime automation. After MCP-driven changes, reopen the relevant Designer section or review [Health](health.md) before reporting the model as ready. diff --git a/docs/en/low-code/index.md b/docs/en/low-code/index.md index 00d47bbbad..b428132003 100644 --- a/docs/en/low-code/index.md +++ b/docs/en/low-code/index.md @@ -176,7 +176,7 @@ The designer stores and reads the same descriptor metadata described in the refe | [Health](health.md) | Selected-layer readiness review across entities, pages, forms, page groups, permissions, and scripts | | [Dashboards](dashboards.md) | Dashboard page descriptors, visualization layout, filters, and runtime data flow | | [Page Groups](page-groups.md) | Dynamic menu folders, nesting, ordering, and page grouping | -| [MCP Integration](mcp.md) | Runtime designer automation with structured reads, validation, apply, and health review | +| [MCP Integration](mcp.md) | Remote MCP endpoint, OpenIddict token setup, and authenticated runtime automation | | [Attributes & Fluent API](fluent-api.md) | Source-controlled C# metadata and runtime overrides | | [Model Descriptor Files](model-json.md) | JSON descriptor files and public descriptor schemas used by the designer and runtime | | [Reference Entities](reference-entities.md) | Lookups to existing entities such as Identity users | diff --git a/docs/en/low-code/mcp.md b/docs/en/low-code/mcp.md index 29c17ee779..cf0f7a7817 100644 --- a/docs/en/low-code/mcp.md +++ b/docs/en/low-code/mcp.md @@ -1,213 +1,158 @@ ```json //[doc-seo] { - "Description": "Use the ABP Low-Code Designer MCP integration to inspect, validate, and apply structured runtime mutations to the database-backed low-code model." + "Description": "Connect remote MCP clients to the ABP Low-Code Designer MCP endpoint with OpenIddict client credentials tokens." } ``` # MCP Integration -> **Preview:** The low-code MCP surface is part of the preview Low-Code System. Tool names, mutation metadata, and validation advice may change before general availability. +> **Preview:** The low-code MCP surface is part of the preview Low-Code System. Endpoint behavior, authorization requirements, and mutation metadata may change before general availability. -The low-code designer exposes a Model Context Protocol (MCP) surface for automation. It is intended for agents and scripted tooling that need to inspect or mutate the same **runtime database-backed** model that the Designer edits in the **Runtime JSON** layer. +The Low-Code Designer exposes a **remote Model Context Protocol (MCP) server** from the running ABP HTTP API host. It is not a local `stdio` tool package. MCP clients connect to your application over HTTP, authenticate with an OpenIddict access token, and work against the same **runtime database-backed** model that the Designer edits in the **Runtime JSON** layer. -## Scope +Use [Model Descriptor Files](model-json.md) when you need source-controlled `_Dynamic/model/**/*.json` files. Use MCP when an agent or automation needs authenticated, structured runtime access that the Designer can immediately show. -The MCP surface is **runtime-only**: +## Remote Endpoint -* It always works against the database-backed runtime model. -* It does not choose between layers at call time. -* It is not the right surface for source-controlled `_Dynamic/model/**/*.json` files. - -Use [Model Descriptor Files](model-json.md) when you need source-controlled descriptors. Use MCP when an agent or automation needs safe, structured changes to the runtime model that the Designer can immediately show. +The low-code MCP endpoint is hosted by the backend application that includes the Low-Code Designer HTTP API module: -## Tool Reference - -All tools below work against the **runtime database-backed** model only. - -### Core Workflow Tools - -| Tool | Use it for | -|------|------------| -| `lowcode_designer_get_capabilities` | Read the server's runtime-only scope, write rules, recommended workflow, and example mutation targets | -| `lowcode_designer_get_mutation_metadata` | Fetch the current `concurrencyStamp` and the valid semantic target tree before planning a write | -| `lowcode_designer_validate_mutations` | Dry-run a mutation batch and get structured validation feedback without writing | -| `lowcode_designer_apply_mutations` | Apply a validated mutation batch to the runtime model; this is the **only write tool** | -| `lowcode_designer_get_health_snapshot` | Re-check the full runtime model after changes to catch broken references or invalid layouts | - -### Entity and Enum Tools - -| Tool | Use it for | -|------|------------| -| `lowcode_designer_get_entities` | List runtime entities; optionally include configured reference entities | -| `lowcode_designer_get_entity` | Read one entity with properties, validators, interceptors, and child metadata | -| `lowcode_designer_get_entity_delete_impact` | Review references that would break or change if an entity is removed | -| `lowcode_designer_get_enum_types` | List available enum types | -| `lowcode_designer_get_enum` | Read one enum and its values | -| `lowcode_designer_get_enum_delete_impact` | Review what depends on an enum before removing it | - -### Page, Form, and Permission Tools - -| Tool | Use it for | -|------|------------| -| `lowcode_designer_get_page_groups` | List page groups used for runtime navigation folders | -| `lowcode_designer_get_pages` | List pages across page types, including dashboard pages | -| `lowcode_designer_get_page` | Read one page descriptor, including columns, filters, dashboard config, and form links | -| `lowcode_designer_get_page_permission_config` | Read the page's permission bindings before changing access rules | -| `lowcode_designer_get_forms` | List forms | -| `lowcode_designer_get_form` | Read one form with fields, flat layout placements, validations, and rules | -| `lowcode_designer_get_form_delete_impact` | Review what depends on a form before removing it | -| `lowcode_designer_get_permissions` | List runtime low-code permission definitions | -| `lowcode_designer_get_permission_delete_impact` | Review where a permission is referenced before removing it | - -### Script and Action Tools - -| Tool | Use it for | -|------|------------| -| `lowcode_designer_get_endpoints` | List scripted custom endpoints | -| `lowcode_designer_get_endpoint` | Read one endpoint with route, method, JavaScript, and analyzed references | -| `lowcode_designer_get_script_autocomplete_metadata` | Discover the script globals, helpers, entities, and metadata available for a script type | -| `lowcode_designer_test_script` | Dry-run endpoint, interceptor, event handler, background job, or background worker JavaScript | -| `lowcode_designer_get_script_event_handlers` | List script event handlers | -| `lowcode_designer_get_script_event_handler` | Read one event handler | -| `lowcode_designer_get_script_background_jobs` | List script background jobs | -| `lowcode_designer_get_script_background_job` | Read one background job | -| `lowcode_designer_get_script_background_worker_scheduler_capabilities` | Read whether the runtime supports dynamic worker registration and cron scheduling | -| `lowcode_designer_get_script_background_workers` | List script background workers | -| `lowcode_designer_get_script_background_worker` | Read one background worker with schedule and JavaScript | - -## Common Sequences - -### Change an Entity or Form - -1. Read the current item with `lowcode_designer_get_entity` or `lowcode_designer_get_form`. -2. Fetch `lowcode_designer_get_mutation_metadata`. -3. Build a small mutation batch against the returned target tree. -4. Run `lowcode_designer_validate_mutations`. -5. Apply with `lowcode_designer_apply_mutations`. -6. Re-read the item and run `lowcode_designer_get_health_snapshot`. - -### Change a Dashboard or Page Group - -1. Read the page with `lowcode_designer_get_page` or list groups with `lowcode_designer_get_page_groups`. -2. Fetch mutation metadata and validate the exact batch. -3. Apply the change. -4. Re-open the page via `lowcode_designer_get_page` and confirm health. - -### Remove a Shared Item Safely - -1. Call the matching delete-impact tool first, such as `lowcode_designer_get_entity_delete_impact`, `lowcode_designer_get_enum_delete_impact`, `lowcode_designer_get_form_delete_impact`, or `lowcode_designer_get_permission_delete_impact`. -2. Fix or remove dependent references. -3. Validate the removal batch. -4. Apply and then re-check health. - -### Review or Debug a Script - -1. Read the action or endpoint with its `get_*` tool. -2. Fetch `lowcode_designer_get_script_autocomplete_metadata` for the relevant script type. -3. Run `lowcode_designer_test_script`. -4. Persist the change through mutations only after the dry run looks correct. - -## Mental Model - -MCP is not a raw JSON document editor. It is a semantic mutation layer over low-code concepts such as: - -* Entities and properties -* Pages, page groups, and dashboards -* Forms and form layout -* Permissions -* Custom endpoints and script actions - -The MCP surface includes read/query capabilities, mutation metadata, dry-run validation, a single mutation apply path, and a health snapshot. The normal workflow is: - -1. Read the current runtime model state for the item you want to change. -2. Fetch the latest mutation metadata and keep its `concurrencyStamp`. -3. Build a small ordered mutation batch that touches only the changed paths. -4. Dry-run the batch with validation. -5. Apply the batch. -6. Re-read the changed item and review [Health](health.md). +```text +https://localhost:/mcp/low-code-designer +``` -## Concurrency and Validation +Connection details: -Every runtime write depends on the latest `concurrencyStamp`. If another write changes the runtime model first, your apply attempt becomes stale and must be rebuilt from the refreshed model state. +* **Transport:** Streamable HTTP / HTTP MCP transport +* **Authentication:** `Authorization: Bearer ` +* **Server name:** `abp-low-code-runtime-designer` +* **Scope:** Runtime database-backed low-code model only -Validation happens before apply and returns structured feedback instead of requiring a client to guess from generic failures. The validation layer checks: +Use the backend host URL, not the React runtime URL and not the Admin Console SPA URL. In tiered solutions, connect to the HTTP API host where the low-code designer API module is loaded. -* Stale concurrency stamps -* Target path syntax -* Missing required input such as `data` or move destinations -* Primitive-only `Set` data -* Final descriptor shape after the batch is simulated -* Entity property type and foreign key rules -* Form layout consistency -* Dashboard layout consistency -* Runtime override rules for descriptors inherited from lower layers +## Required Permissions -Treat validation as part of the normal write flow, not as an optional extra. +The endpoint requires the Low-Code Designer permission group: -## Mutation Model +| Permission | Required for | +|------------|--------------| +| `AbpLowCodeDesigner.Default` | Connecting and reading runtime model metadata | +| `AbpLowCodeDesigner.Edit` | Validating and applying runtime model changes | +| `AbpLowCodeDesigner.ScriptTest` | Running script dry-runs through MCP | -Runtime writes are intentionally narrow: +Grant these permissions to the **OpenIddict application/client** that will request the token, not only to a user or role. In Admin Console, use the permission action on the OpenIddict application row and grant the required Low-Code Designer permissions for the client. -* `Add` creates a keyed descriptor or collection member. -* `Set` changes a scalar value or a supported primitive list. -* `Remove` deletes the semantic target. -* `Move` relocates an existing node without resending the whole object. +See the [Permission Management Module](../modules/permission-management.md#permission-management-dialog) for the standard permission dialog behavior. -Important behavior: +## Create an Access Token -* `Set` data must stay primitive: string, number, boolean, `null`, or a supported primitive string list. -* Do not replace whole descriptor trees when only one field changed. -* Keep batches small and semantic. Send changed paths, not full model payloads. -* If a mapped entity or property is removed with drop behavior, the runtime model can also remove the physical table or column in the runtime layer. +For unattended MCP automation, create a dedicated OpenIddict application instead of reusing an interactive user token. -## Runtime Override and Schema Rules +1. Open **Admin Console**. +2. Go to **OpenIddict** > **Applications**. +3. Create a new application, for example `LowCodeMcpClient`. +4. Set **Client type** to `Confidential client`. +5. Set a strong **Client secret** and store it securely. +6. Open the **Authorization** tab and enable **Allow client credentials flow**. +7. Open the **Scopes** tab and allow the API scope used by the backend that hosts the low-code APIs, for example ``. +8. Save the application. +9. From the application row, open **Permissions** and grant the Low-Code Designer permissions required by your MCP scenario. -Runtime MCP writes can extend descriptors that originate from lower layers, but they do not have unlimited control over inherited schema. +The OpenIddict application and scope management screens are described in [Creating a Client Credentials Application](../modules/openiddict-pro.md#creating-a-client-credentials-application). -For entity properties inherited from a lower layer, runtime edits are intentionally restricted. Typical runtime-safe changes are display labels and runtime-owned validators. Inherited storage details such as type, database mapping, default value, required or unique behavior, foreign key settings, and file or image storage options remain immutable in runtime. +The Admin Console application screen should show the confidential client with **Allow client credentials flow** enabled: -This separation matches the low-code layer model: +![openiddict-client-credentials-application](../images/openiddict-client-credentials-application.png) -* Runtime database-backed changes use **direct** schema mutation. -* Source-controlled JSON layer changes use the normal **migration** workflow. +Request an access token from the OpenIddict authority with the saved client id, client secret, and selected API scope. In non-tiered solutions this is usually the same backend host; in tiered solutions it is usually the Auth Server URL: -If you are working in `_Dynamic/model`, MCP is the wrong tool. Use the source-controlled descriptor flow and migrations instead. +```bash +curl -X POST "https://localhost:/connect/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=client_credentials" \ + -d "client_id=LowCodeMcpClient" \ + -d "client_secret=" \ + -d "scope=" +``` -## Layout and Type Conventions +Use the returned `access_token` as the bearer token in the MCP client configuration. -Several conventions matter when MCP clients generate mutations: +```text +Authorization: Bearer +``` -* Use canonical lowercase entity property types: `string`, `int`, `long`, `decimal`, `datetime`, `boolean`, `guid`, `enum`, `date`, `time`, `file`, `image`, `money`. -* Use canonical lowercase form field types: `text`, `textarea`, `number`, `checkbox`, `date`, `datetime`, `select`, `lookup`, `guid`, `computed`, `time`, `file`, `image`, `money`. -* Form layout is flat and id-keyed under `layout.tabs[].groups[].fields[]`. Each placement carries `row`, `colSpan`, and optional `colStart`. -* Dashboard layout is flat and name-keyed under `dashboard.visualizations[]`. Each visualization carries `row`, `order`, and `width`. -* Page and page-group icons are CSS class strings, not URLs or image file paths. -* For foreign access, `foreignKey.access` values are `none`, `view`, or `edit`. +## Connect From An MCP Client -These rules matter because validation and runtime rendering assume them. For example, a form can define fields correctly but still render an empty group if no valid placements point to those field IDs. +For ABP AI Management or another MCP client that supports remote HTTP servers, create a server entry with: -## Designer and MCP Together +| Setting | Value | +|---------|-------| +| Name | `ABP Low-Code Designer` | +| Transport | HTTP / Streamable HTTP | +| Endpoint URL | `https://localhost:/mcp/low-code-designer` | +| Authentication | Bearer token | +| Token | The OpenIddict access token created for `LowCodeMcpClient` | -Use the Designer when you want: +For clients that use JSON configuration, the same connection usually looks like this: -* Interactive editing -* Visual context for entities, pages, forms, and permissions -* Manual review before publishing +```json +{ + "mcpServers": { + "abp-low-code-designer": { + "type": "streamable-http", + "url": "https://localhost:/mcp/low-code-designer", + "headers": { + "Authorization": "Bearer " + } + } + } +} +``` + +Client configuration names differ by product. If your client uses `http`, `streamableHttp`, or a separate `authorization` field, keep the same endpoint URL and bearer token. -Use MCP when you want: +## Runtime-Only Scope -* Agent-driven or scripted changes -* Repeatable runtime mutation workflows -* Structured validation before write -* Safe, incremental edits instead of raw JSON replacement +The MCP surface is **runtime-only**: + +* It always reads and writes the database-backed runtime model. +* It does not choose between source-controlled and runtime layers at call time. +* It does not edit source-controlled `_Dynamic/model/**/*.json` descriptor files. +* It does not replace the normal migration workflow for source-controlled model changes. + +Runtime MCP writes can extend descriptors that originate from lower layers, but inherited storage details remain restricted. For example, runtime edits can typically change display labels and runtime-owned validators, but cannot change inherited property type, database mapping, required or unique behavior, foreign key settings, or file and image storage options. + +## Safe Automation Workflow + +After the MCP client connects, let it discover the available capabilities from the server. The normal write workflow should still be conservative: + +1. Read the current runtime item before planning a change. +2. Fetch the current mutation metadata and concurrency stamp. +3. Build a small mutation batch that touches only the changed semantic paths. +4. Validate the batch before writing. +5. Apply the validated batch. +6. Re-read the changed item and review [Health](health.md). + +Treat validation and health review as part of the normal MCP workflow. They are especially important for forms, dashboard layouts, relation changes, and delete operations that can leave broken references. + +## Troubleshooting + +| Problem | Check | +|---------|-------| +| `401 Unauthorized` | The MCP client is not sending `Authorization: Bearer `, the token expired, or the token was issued by an authority that the backend host does not trust. | +| `403 Forbidden` | The OpenIddict client does not have the required `AbpLowCodeDesigner.*` permissions. | +| Client cannot connect | Verify that the backend host is running and that the URL points to `/mcp/low-code-designer` on the HTTP API host. | +| Writes fail | Grant `AbpLowCodeDesigner.Edit`, refresh the token, and rebuild the change from the latest runtime metadata. | +| Script dry-run fails with authorization | Grant `AbpLowCodeDesigner.ScriptTest` and generate a new token. | + +## Designer and MCP Together -The two surfaces are complementary. A common workflow is to inspect or prototype in the Designer, automate a repeatable mutation flow through MCP, then reopen the Designer and [Health](health.md) to confirm the result. +Use the Designer when you want interactive editing and visual review. Use MCP when a remote agent or automation needs authenticated, repeatable runtime changes. After MCP-driven changes, reopen the relevant Designer section or review [Health](health.md) before treating the runtime model as ready. ## See Also * [Low-Code Designer](designer.md) * [Health](health.md) -* [Dashboards](dashboards.md) -* [Page Groups](page-groups.md) * [Model Descriptor Files](model-json.md) +* [OpenIddict Module (Pro)](../modules/openiddict-pro.md#creating-a-client-credentials-application) +* [Permission Management Module](../modules/permission-management.md#permission-management-dialog) diff --git a/docs/en/modules/openiddict-pro.md b/docs/en/modules/openiddict-pro.md index 94d8deb631..9d6cae0484 100644 --- a/docs/en/modules/openiddict-pro.md +++ b/docs/en/modules/openiddict-pro.md @@ -50,6 +50,44 @@ You can create new application or edit existing applications in this page: ![openiddict-edit-application-modal](../images/openiddict-edit-application-modal.png) +##### Creating a Client Credentials Application + +Use a client credentials application when a machine-to-machine client, automation, or MCP client needs to call protected backend APIs without an interactive user login. + +1. Open **Administration** > **OpenIddict** > **Applications**. +2. Click **New Application**. +3. Enter a unique **Client Id**, for example `InternalAutomationClient`. +4. Set **Client Type** to `Confidential client`. +5. Enter a strong **Client Secret** and store it securely. The secret is required when the client requests a token. +6. Open the **Authorization** tab and enable **Allow client credentials flow**. +7. Open the **Scopes** tab and select the API scopes the client can request. +8. Save the application. + +The application screen should show the `client_credentials` grant enabled. Use the **Scopes** tab to select the API scope that the client can request. + +![openiddict-client-credentials-application](../images/openiddict-client-credentials-application.png) + +If the client will call APIs protected by ABP permissions, grant permissions to the application after saving it. Open the application row's **Actions** menu, select **Permissions**, and grant the required permissions for the **Client (OpenIddict Applications)** provider. + +Request an access token from the OpenIddict token endpoint with the `client_credentials` grant: + +```bash +curl -X POST "https://localhost:/connect/token" \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=client_credentials" \ + -d "client_id=InternalAutomationClient" \ + -d "client_secret=" \ + -d "scope=" +``` + +Use the returned `access_token` as a bearer token when calling protected APIs: + +```text +Authorization: Bearer +``` + +In non-tiered applications, the OpenIddict authority is typically the backend host. In tiered applications, use the Auth Server URL for `/connect/token`. + #### API Scope Management OpenIddict module allows to manage API scope. To allow applications to request access tokens for APIs, you need to define API scopes.