From e3d442e3918bc9468e8f13a89a384da5a1ac576c Mon Sep 17 00:00:00 2001 From: Saurabh Badenkal Date: Sun, 4 Oct 2026 21:12:38 -0700 Subject: [PATCH 1/3] fix: improve dv-connect CI routing and workspace safety --- .cursor-plugin/marketplace.json | 4 ++-- .github/plugin/marketplace.json | 4 ++-- .github/plugins/dataverse/.claude-plugin/plugin.json | 2 +- .github/plugins/dataverse/.codex-plugin/plugin.json | 2 +- .github/plugins/dataverse/.cursor-plugin/plugin.json | 2 +- .github/plugins/dataverse/.github/plugin/plugin.json | 2 +- .github/plugins/dataverse/gemini-extension.json | 4 ++-- .github/plugins/dataverse/skills/dv-connect/SKILL.md | 6 ++++-- 8 files changed, 14 insertions(+), 12 deletions(-) diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json index 7cf65f5..2bf491e 100644 --- a/.cursor-plugin/marketplace.json +++ b/.cursor-plugin/marketplace.json @@ -3,7 +3,7 @@ "name": "dataverse-skills", "metadata": { "description": "Official Dataverse plugin marketplace for Cursor", - "version": "1.15.0" + "version": "1.15.1" }, "owner": { "name": "Microsoft", @@ -14,7 +14,7 @@ "name": "dataverse", "description": "Microsoft Dataverse plugin for coding agents, covering record CRUD, bulk data operations, advanced queries, schema and metadata, administration, security, environment management, and solution lifecycle through MCP, CLI, and SDK workflows.", "source": "./.github/plugins/dataverse", - "version": "1.15.0", + "version": "1.15.1", "homepage": "https://github.com/microsoft/Dataverse-skills" } ] diff --git a/.github/plugin/marketplace.json b/.github/plugin/marketplace.json index de5cf5b..b5fdf37 100644 --- a/.github/plugin/marketplace.json +++ b/.github/plugin/marketplace.json @@ -2,7 +2,7 @@ "name": "dataverse-skills", "metadata": { "description": "Official Dataverse plugin marketplace for agent-guided development", - "version": "1.15.0" + "version": "1.15.1" }, "owner": { "name": "Microsoft", @@ -13,7 +13,7 @@ "name": "dataverse", "description": "Microsoft Dataverse plugin for coding agents, covering record CRUD, bulk data operations, advanced queries, schema and metadata, administration, security, environment management, and solution lifecycle through MCP, CLI, and SDK workflows.", "source": "./.github/plugins/dataverse", - "version": "1.15.0", + "version": "1.15.1", "homepage": "https://github.com/microsoft/Dataverse-skills" } ] diff --git a/.github/plugins/dataverse/.claude-plugin/plugin.json b/.github/plugins/dataverse/.claude-plugin/plugin.json index 848e231..d10940a 100644 --- a/.github/plugins/dataverse/.claude-plugin/plugin.json +++ b/.github/plugins/dataverse/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "dataverse", "description": "Microsoft Dataverse plugin for coding agents, covering record CRUD, bulk data operations, advanced queries, schema and metadata, administration, security, environment management, and solution lifecycle through MCP, CLI, and SDK workflows.", - "version": "1.15.0", + "version": "1.15.1", "author": { "name": "Microsoft", "url": "https://www.microsoft.com" diff --git a/.github/plugins/dataverse/.codex-plugin/plugin.json b/.github/plugins/dataverse/.codex-plugin/plugin.json index 7a7d4bb..6f2e296 100644 --- a/.github/plugins/dataverse/.codex-plugin/plugin.json +++ b/.github/plugins/dataverse/.codex-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "dataverse", "description": "Microsoft Dataverse plugin for coding agents, covering record CRUD, bulk data operations, advanced queries, schema and metadata, administration, security, environment management, and solution lifecycle through MCP, CLI, and SDK workflows.", - "version": "1.15.0", + "version": "1.15.1", "author": { "name": "Microsoft", "url": "https://www.microsoft.com" diff --git a/.github/plugins/dataverse/.cursor-plugin/plugin.json b/.github/plugins/dataverse/.cursor-plugin/plugin.json index 74bdb49..39ad87e 100644 --- a/.github/plugins/dataverse/.cursor-plugin/plugin.json +++ b/.github/plugins/dataverse/.cursor-plugin/plugin.json @@ -2,7 +2,7 @@ "name": "dataverse", "displayName": "Microsoft Dataverse", "description": "Microsoft Dataverse plugin for coding agents, covering record CRUD, bulk data operations, advanced queries, schema and metadata, administration, security, environment management, and solution lifecycle through MCP, CLI, and SDK workflows.", - "version": "1.15.0", + "version": "1.15.1", "author": { "name": "Microsoft", "url": "https://www.microsoft.com" diff --git a/.github/plugins/dataverse/.github/plugin/plugin.json b/.github/plugins/dataverse/.github/plugin/plugin.json index 3796e5c..534709d 100644 --- a/.github/plugins/dataverse/.github/plugin/plugin.json +++ b/.github/plugins/dataverse/.github/plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "dataverse", "description": "Microsoft Dataverse plugin for coding agents, covering record CRUD, bulk data operations, advanced queries, schema and metadata, administration, security, environment management, and solution lifecycle through MCP, CLI, and SDK workflows.", - "version": "1.15.0", + "version": "1.15.1", "author": { "name": "Microsoft", "url": "https://www.microsoft.com" diff --git a/.github/plugins/dataverse/gemini-extension.json b/.github/plugins/dataverse/gemini-extension.json index e64c45d..39ba10d 100644 --- a/.github/plugins/dataverse/gemini-extension.json +++ b/.github/plugins/dataverse/gemini-extension.json @@ -1,6 +1,6 @@ { "name": "dataverse", - "version": "1.15.0", + "version": "1.15.1", "description": "Microsoft Dataverse plugin for coding agents, covering record CRUD, bulk data operations, advanced queries, schema and metadata, administration, security, environment management, and solution lifecycle through MCP, CLI, and SDK workflows.", "settings": [ { @@ -20,7 +20,7 @@ "${DATAVERSE_URL}" ], "env": { - "DATAVERSE_OPERATION_CONTEXT": "app=dataverse-skills/1.15.0;skill=mcp-direct;agent=gemini-cli" + "DATAVERSE_OPERATION_CONTEXT": "app=dataverse-skills/1.15.1;skill=mcp-direct;agent=gemini-cli" } } } diff --git a/.github/plugins/dataverse/skills/dv-connect/SKILL.md b/.github/plugins/dataverse/skills/dv-connect/SKILL.md index 15958bb..bd1fa77 100644 --- a/.github/plugins/dataverse/skills/dv-connect/SKILL.md +++ b/.github/plugins/dataverse/skills/dv-connect/SKILL.md @@ -1,11 +1,13 @@ --- name: dv-connect -description: One-step setup and connection diagnostics for a Dataverse environment — installs tools, authenticates, registers MCP, writes `.env`, and verifies active profiles and linked ERP endpoints. Use when starting a new project, switching environments, fixing authentication, troubleshooting MCP, or checking existing Dataverse / Finance and Operations connectivity or linkage. +description: One-step Dataverse connection setup and diagnostics — verifies WhoAmI, reuses injected non-interactive credentials, installs tools, authenticates, registers MCP, and writes `.env`. Use when starting a project, checking an existing or CI connection, switching environments, fixing authentication, troubleshooting MCP, or verifying linked Finance and Operations endpoints. --- # Skill: Connect -One-step, idempotent Dataverse connection. Each step checks if it's already done and skips. +> ## Critical workspace safety rules — read first +> 1. In CI, reuse injected auth and verify only. Never start browser or device-code login. +> 2. Never replace `.gitignore`; append missing entries and preserve every existing line. > **Environment-First Rule** — All metadata and plugin registrations are created **in the environment** via API/scripts, then pulled into the repo. Never hand-write solution XML to create components. From d12f2cd0b08881a73a62e7ba09fbda06fb888516 Mon Sep 17 00:00:00 2001 From: Saurabh Badenkal Date: Sun, 4 Oct 2026 21:29:53 -0700 Subject: [PATCH 2/3] fix: keep Dataverse writes on managed surfaces --- .../plugins/dataverse/skills/dv-data/SKILL.md | 2 +- .../dataverse/skills/dv-metadata/SKILL.md | 21 +--------- .../references/currency-columns.md | 38 +++++++++++++++++++ 3 files changed, 40 insertions(+), 21 deletions(-) create mode 100644 .github/plugins/dataverse/skills/dv-metadata/references/currency-columns.md diff --git a/.github/plugins/dataverse/skills/dv-data/SKILL.md b/.github/plugins/dataverse/skills/dv-data/SKILL.md index f2d2403..4e78351 100644 --- a/.github/plugins/dataverse/skills/dv-data/SKILL.md +++ b/.github/plugins/dataverse/skills/dv-data/SKILL.md @@ -64,7 +64,7 @@ import requests # WRONG for SDK-supported ops Forms/views (`systemform`/`savedquery`) **are** ordinary records — create/modify them with `client.records.*` (see **dv-metadata**), and read N:N with `records.list(expand=...)`. For the genuine gaps below, prefer the managed `dataverse api` escape hatch over raw `urllib`: - Global option sets — see **dv-metadata** -- N:N record association — CLI `dataverse data associate`, or `POST /api/data/v9.2/()//$ref` +- N:N record association — CLI `dataverse data associate` / `disassociate`; set N:1 lookups with `client.records.update()` - `$apply` aggregation — use `client.query.fetchxml()`; see **dv-query** - Unbound actions (e.g., `PublishXml`, `InstallSampleData`) — `dataverse api request`/`invoke` - DeleteMultiple, general OData batching diff --git a/.github/plugins/dataverse/skills/dv-metadata/SKILL.md b/.github/plugins/dataverse/skills/dv-metadata/SKILL.md index 4d702b6..6e8b370 100644 --- a/.github/plugins/dataverse/skills/dv-metadata/SKILL.md +++ b/.github/plugins/dataverse/skills/dv-metadata/SKILL.md @@ -154,7 +154,7 @@ created = client.tables.add_columns( print(created) # ['new_Description', 'new_Amount', 'new_Active'] ``` -Supported type strings: `"string"` / `"text"`, `"int"` / `"integer"`, `"decimal"` / `"money"`, `"float"` / `"double"`, `"datetime"` / `"date"`, `"bool"` / `"boolean"`, `"file"`, and `Enum` subclasses (for local option sets). +Supported type strings: `"string"` / `"text"`, `"int"` / `"integer"`, `"decimal"`, `"float"` / `"double"`, `"datetime"` / `"date"`, `"bool"` / `"boolean"`, `"file"`, and `Enum` subclasses (for local option sets). For true currency, SDK `"money"` is currently Decimal; use the managed path in [currency-columns.md](references/currency-columns.md). **Choice (picklist) column via SDK:** @@ -172,25 +172,6 @@ created = client.tables.add_columns( ) ``` -**Web API approach (needed for column types the SDK doesn't support — e.g., currency with precision, memo with custom max length):** - -```python -# Currency column -attribute = { - "@odata.type": "Microsoft.Dynamics.CRM.MoneyAttributeMetadata", - "SchemaName": "new_amount", - "DisplayName": {"@odata.type": "Microsoft.Dynamics.CRM.Label", - "LocalizedLabels": [{"@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", - "Label": "Amount", "LanguageCode": 1033}]}, - "RequiredLevel": {"Value": "None"}, - "MinValue": 0, - "MaxValue": 1000000000, - "Precision": 2, - "PrecisionSource": 2 -} -# POST to /api/data/v9.2/EntityDefinitions(LogicalName='new_projectbudget')/Attributes -``` - --- ## Lookup Columns and Relationships diff --git a/.github/plugins/dataverse/skills/dv-metadata/references/currency-columns.md b/.github/plugins/dataverse/skills/dv-metadata/references/currency-columns.md new file mode 100644 index 0000000..6321178 --- /dev/null +++ b/.github/plugins/dataverse/skills/dv-metadata/references/currency-columns.md @@ -0,0 +1,38 @@ +# Currency columns + +The Python SDK currently maps both `"decimal"` and `"money"` to `DecimalAttributeMetadata`. For a true Dataverse currency column, use the managed `dataverse api request` escape hatch with `MoneyAttributeMetadata`. Do not send metadata payloads with `requests` or `urllib`. + +Create the payload file with Python: + +```python +import json + +attribute = { + "@odata.type": "Microsoft.Dynamics.CRM.MoneyAttributeMetadata", + "SchemaName": "new_amount", + "DisplayName": { + "@odata.type": "Microsoft.Dynamics.CRM.Label", + "LocalizedLabels": [{ + "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", + "Label": "Amount", + "LanguageCode": 1033, + }], + }, + "RequiredLevel": {"Value": "None"}, + "MinValue": 0, + "MaxValue": 1000000000, + "Precision": 2, + "PrecisionSource": 2, +} + +with open("money-column.json", "w", encoding="utf-8") as payload_file: + json.dump(attribute, payload_file) +``` + +Send it through the authenticated CLI and associate it with the solution: + +``` +dataverse api request --target dataverse --method POST --path "/api/data/v9.2/EntityDefinitions(LogicalName='new_projectbudget')/Attributes" --body-file money-column.json --header "MSCRM.SolutionUniqueName:MySolution" --context "app=dataverse-skills/;skill=dv-metadata;agent=" +``` + +After creation, read the column metadata and confirm `AttributeType` is `Money` before reporting success. From 5c6d0a28b5fe6f7f80ebffeefc251787f19e3a1b Mon Sep 17 00:00:00 2001 From: Saurabh Badenkal Date: Sun, 4 Oct 2026 23:49:38 -0700 Subject: [PATCH 3/3] fix: clarify managed record association --- .github/plugins/dataverse/skills/dv-data/SKILL.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/plugins/dataverse/skills/dv-data/SKILL.md b/.github/plugins/dataverse/skills/dv-data/SKILL.md index 4e78351..0fba933 100644 --- a/.github/plugins/dataverse/skills/dv-data/SKILL.md +++ b/.github/plugins/dataverse/skills/dv-data/SKILL.md @@ -64,7 +64,7 @@ import requests # WRONG for SDK-supported ops Forms/views (`systemform`/`savedquery`) **are** ordinary records — create/modify them with `client.records.*` (see **dv-metadata**), and read N:N with `records.list(expand=...)`. For the genuine gaps below, prefer the managed `dataverse api` escape hatch over raw `urllib`: - Global option sets — see **dv-metadata** -- N:N record association — CLI `dataverse data associate` / `disassociate`; set N:1 lookups with `client.records.update()` +- Record association — CLI `dataverse data associate` / `disassociate` supports N:N and lookup navigation properties; `client.records.update()` is the scripted N:1 lookup path - `$apply` aggregation — use `client.query.fetchxml()`; see **dv-query** - Unbound actions (e.g., `PublishXml`, `InstallSampleData`) — `dataverse api request`/`invoke` - DeleteMultiple, general OData batching @@ -86,7 +86,7 @@ dataverse data upsert --table accounts --key "accountnumber='ACC-001'" --data '{ # Delete (--no-confirm skips the prompt) dataverse data delete --table accounts --id --no-confirm --context "app=dataverse-skills/;skill=dv-data;agent=" -# Associate two records (N:N or lookup) +# Link an existing contact to its parent account using the IDs returned by create dataverse data associate --table accounts --id --relationship contact_customer_accounts --related contacts --related-id --context "app=dataverse-skills/;skill=dv-data;agent=" # Disassociate (N:N — pass --related-id; clear a lookup — omit --related-id) @@ -164,6 +164,14 @@ print(f"Created: {guid}") | System polymorphic: `customerid` | `customerid_account@odata.bind` | ~~`customerid@odata.bind`~~ | | System: `parentcustomerid` | `parentcustomerid_account@odata.bind` | ~~`_parentcustomerid_value@odata.bind`~~ | +For an account/contact N:1 link, update the contact side with the IDs returned by the create calls; do not handcraft a raw `$ref` request: + +```python +client.records.update("contact", contact_id, { + "parentcustomerid_account@odata.bind": f"/accounts({account_id})", +}) +``` + ### Find the Navigation Property Name After creating a lookup via SDK: `result.lookup_schema_name` is the navigation property name.