[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-microsoft-dv-connect":3,"mdc--a3n6ee-key":40,"related-org-microsoft-dv-connect":3012,"related-repo-microsoft-dv-connect":3206},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":23,"repoUrl":24,"updatedAt":25,"license":26,"forks":27,"topics":28,"repo":35,"sourceUrl":38,"mdContent":39},"dv-connect","connect to Dataverse environments","One-step setup for a Dataverse environment — installs tools, authenticates, registers the MCP server, and writes `.env`. Use when starting a new project, switching environments, fixing authentication, or troubleshooting an MCP connection that won't come up.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"microsoft","Microsoft","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fmicrosoft.png",[12,16,17,20],{"name":13,"slug":14,"type":15},"Configuration","configuration","tag",{"name":9,"slug":8,"type":15},{"name":18,"slug":19,"type":15},"MCP","mcp",{"name":21,"slug":22,"type":15},"Dataverse","dataverse",184,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FDataverse-skills","2026-07-31T05:54:51.062501",null,48,[29,22,30,31,19,32,33,34],"agent-skills","dynamics-365","dynamics-crm","mcp-server","plugin","power-platform",{"repoUrl":24,"stars":23,"forks":27,"topics":36,"description":37},[29,22,30,31,19,32,33,34],"Microsoft Dataverse skills for AI coding agents. Wraps the Dataverse MCP server, Dataverse CLI, Python SDK, and PAC CLI behind specialist skills for building, querying, deploying, and administering Dataverse environments.","https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002FDataverse-skills\u002Ftree\u002FHEAD\u002F.github\u002Fplugins\u002Fdataverse\u002Fskills\u002Fdv-connect","---\nname: dv-connect\ndescription: One-step setup for a Dataverse environment — installs tools, authenticates, registers the MCP server, and writes `.env`. Use when starting a new project, switching environments, fixing authentication, or troubleshooting an MCP connection that won't come up.\n---\n\n# Skill: Connect\n\nOne-step connection to Dataverse. Handles tool installation, authentication, environment selection, workspace initialization, MCP configuration, and verification — all idempotently. Each step checks if it's already done and skips if so.\n\n> **Environment-First Rule** — All metadata (solutions, columns, tables, forms, views) and plugin registrations are created **in the Dynamics environment** via API or scripts, then pulled into the repo. Never write or edit solution XML by hand to create new components.\n\n**Execute every step in order.** Do not skip ahead, even if a later step appears more relevant to the user's immediate goal. **Exception:** Step 0 below can short-circuit the entire flow if the workspace is already set up.\n\n---\n\n## Step 0: Detect existing setup (run this first)\n\nBefore touching anything, check whether this workspace is already connected to a Dataverse environment. This matters a lot on `claude --continue` or any re-run — repeating it on an already-configured workspace overwrites `.env`, re-registers MCP, and wastes time.\n\nRun these checks in order. If **all four pass**, skip straight to Step 7 (final verification) and stop there.\n\n1. **`.env` is present and complete** — file exists at the workspace root and contains non-empty values for `DATAVERSE_URL`, `TENANT_ID`, and `MCP_CLIENT_ID`\n2. **MCP is registered** — `.mcp.json` (Claude Code) or the equivalent Copilot \u002F Cursor config file has a `dataverse-*` server entry pointing at the `DATAVERSE_URL` from `.env`\n3. **Both auth surfaces match `.env`** — `dataverse auth who` shows a profile whose `Environment Url` matches `DATAVERSE_URL`, AND `pac org who` against a PAC profile for the same URL succeeds. (DV CLI auth covers Connect \u002F Data \u002F Query \u002F Metadata \u002F MCP \u002F Python; PAC auth covers `dv-solution` and `dv-admin`. Both are front-loaded at connect time so neither prompts later.)\n4. **Python SDK is importable and current** — `python -c \"from PowerPlatform.Dataverse.client import DataverseClient; import pandas; from importlib.metadata import version; v=version('PowerPlatform-Dataverse-Client'); assert int(v.split('.')[0])>=1, f'SDK {v} is outdated, need >=1.0.0'\"` exits 0\n\n**If all pass:** Tell the user you detected an existing setup, list what you found (URL, profile name, MCP server name), then jump to Step 7. Do not rewrite `.env`, do not re-register MCP, do not re-run `pip install`.\n\n> Example: \"Detected existing Dataverse setup at `{DATAVERSE_URL}` (auth profile: `{PROFILE}`, MCP server: `dataverse-{orgid}`). Running verification only.\"\n\n**If any check fails:** Proceed through the normal flow (Steps 1–7), but still use each step's own skip condition. A partially-configured workspace doesn't need a full redo — e.g., if only `.env` and MCP are missing but tools and auth are fine, start at Step 2 or Step 3.\n\n---\n\n## Step 1: Ensure tools are installed\n\nCheck each tool independently — **do not use fail-fast parallel execution.** If one tool check fails, continue checking the others so you can report all missing tools at once. See [tools-setup.md](references\u002Ftools-setup.md) for installation commands and platform-specific notes.\n\n| Tool | Check |\n|---|---|\n| Python 3 | `python --version` |\n| Git | `git --version` |\n| Node.js | `node --version` |\n| PAC CLI | `pac` (prints version banner; note: `pac --version` is not a valid command and returns a non-zero exit code) (see [tools-setup.md](references\u002Ftools-setup.md) for Windows path discovery if not in PATH) |\n| Dataverse CLI | `npm list -g @microsoft\u002Fdataverse` (prints `@microsoft\u002Fdataverse@\u003Cversion>` if installed globally; prints `(empty)` if not) |\n| .NET SDK | `dotnet --version` |\n| Azure CLI | `az --version` |\n\n.NET SDK is needed for PAC CLI but NOT for the Dataverse CLI (the npm package bundles its own runtime). Node.js powers the Dataverse CLI npm package (`@microsoft\u002Fdataverse`), which is used as the MCP proxy and for scripted data plane actions. Azure CLI is used as a fallback for environment discovery when PAC CLI isn't available (see [mcp-configuration.md](references\u002Fmcp-configuration.md) Step 3b). GitHub CLI is not needed for connecting — it's used later for ALM\u002FCI\u002FCD scenarios (see `dv-solution`).\n\nIf any tool is missing, install it (see [tools-setup.md](references\u002Ftools-setup.md)), then verify. If `winget` installs a tool but it's not in PATH, ask the user to restart the terminal.\n\nAfter Python is confirmed:\n```\npip install --upgrade azure-identity requests PowerPlatform-Dataverse-Client pandas msal msal-extensions\n```\n\n`msal` + `msal-extensions` let `scripts\u002Fauth.py` reuse the `dataverse auth create` cache \\u2014 one sign-in for CLI, MCP, Python.\n\nAfter Node.js is confirmed, install or upgrade the Dataverse CLI to the latest version (run on each connect to keep it current):\n```\nnpm install -g @microsoft\u002Fdataverse@latest\n```\n\n**Skip condition:** All tools present, Python SDK installed, and `pandas` importable (`python -c \"import pandas\"`).\n\n---\n\n## Step 2: Discover and select the environment\n\nBefore asking the user for a URL, check what's already available.\n\n> **Auth tool choice.** Two tools, two AAD apps, two caches — front-load both at connect:\n>\n> 1. **`dataverse auth create`** (app `0c412cc3-…`) covers DV CLI + MCP + Python.\n> 2. **`pac auth create`** (PAC's own app) covers `dv-solution` + `dv-admin`.\n\nCheck for an existing DV CLI profile first, then fall back to PAC for environment discovery if needed:\n\n```\ndataverse auth list\ndataverse auth who\npac auth list   # PAC profiles are still useful for env discovery \u002F pac org list\n```\n\n**If `dataverse auth who` shows a profile and its environment matches the user's target:**\n- Reuse it. Set `DATAVERSE_URL` and `TENANT_ID` from the profile.\n\n**If no DV CLI profile exists (or it points at the wrong environment):**\n- Ask: \"Do you want to connect to an existing environment or create a new one?\"\n\n**Before selecting, check for tenant\u002Fregion mismatch.** If the target environment URL uses a different region (e.g., `crm10.dynamics.com` = APAC) than the currently authenticated account's environments, create a new profile for the correct tenant rather than trying to reuse the old one:\n\n```\ndataverse auth create --environment \u003Curl>          # interactive (WAM broker on Windows → no browser tab)\ndataverse auth create --environment \u003Curl> --deviceCode   # headless \u002F remote \u002F SSH\n```\n\nIf the user hits an admin-consent error, the CLI prints the correct scope-scoped consent URL to share with a tenant admin — do not synthesize one.\n\n**To switch between existing DV CLI profiles:**\n```\ndataverse auth select --name \u003Cprofile-name>\n```\n\n**To create a new environment** (requires admin permissions):\n```\npac admin create --name \"\u003Cname>\" --type \"\u003Ctype>\" --region \"\u003Cregion>\"\n```\nIf this fails with permissions error, guide the user to [Power Platform Admin Center](https:\u002F\u002Fadmin.powerplatform.microsoft.com\u002F) to create it, then connect.\n\n**Confirm connection:**\n```\ndataverse auth who\ndataverse org who      # or: pac org who\n```\nParse the output to extract `DATAVERSE_URL`, `TENANT_ID`, and — on ERP-linked envs — `ERP_URL` (see [`erp-detection.md`](references\u002Ferp-detection.md)).\n\nIf neither command shows a tenant ID, fall back to:\n```bash\ncurl -sI https:\u002F\u002F\u003Corg>.crm.dynamics.com\u002Fapi\u002Fdata\u002Fv9.2\u002F \\\n  | grep -i \"WWW-Authenticate\" \\\n  | sed -n 's|.*login\\.microsoftonline\\.com\u002F\\([^\u002F]*\\).*|\\1|p'\n```\n\n### Step 2b: Front-load PAC CLI auth for the same environment\n\nPAC uses its own AAD app, so a separate sign-in is required for `dv-solution` and `dv-admin`. Do it now — user signs in twice back-to-back, no later surprises.\n\n```\npac auth list                                       # skip if a profile for $DATAVERSE_URL exists\npac auth create --name \u003Corgid> --environment \u003CDATAVERSE_URL>\n```\n\nUse the same account as Step 2. If PAC CLI is not installed, skip with a note that `dv-solution` \u002F `dv-admin` will need it later.\n\n\n---\n\n## Step 3: Create .env\n\nPresent authentication options:\n\n> How would you like to authenticate with Dataverse?\n> 1. **Interactive login (recommended)** — Sign in via browser. No app registration needed. Token stays cached across sessions.\n> 2. **Service principal (for CI\u002FCD)** — Uses CLIENT_ID and CLIENT_SECRET from an Azure app registration.\n\nWrite `.env` directly — do not instruct the user to create it:\n\nDetect the current tool (Claude or Copilot) from context and set `MCP_CLIENT_ID` automatically:\n- Claude (CLI or VSCode extension): `0c412cc3-0dd6-449b-987f-05b053db9457`\n- GitHub Copilot: `aebc6443-996d-45c2-90f0-388ff96faa56`\n\nAlso set plugin attribution variables for User-Agent tagging. **Fill in the two literals below from your own context** — you (the agent) loaded this plugin, so you already know both values:\n\n- `PLUGIN_VERSION` — the `version` field of your loaded plugin manifest (e.g. `\"1.5.0\"`). At runtime, `auth.py` re-reads this from the live manifest via host env vars; this `.env` entry is a fallback for offline cases.\n- `AGENT` — your host identity, one of: `claude-code`, `copilot`, `cursor`, `codex`, or `unknown`. Must match an entry in `_ALLOWED_AGENTS` in `auth.py` — if you don't recognize your host, use `unknown`.\n\n```python\n# Substitute these two literals from your loaded plugin context.\n# Do NOT leave the angle-bracket placeholders — replace with real values.\nplugin_version = \"\u003Cplugin manifest version, e.g. 1.5.0>\"\nagent_host = \"\u003Cyour host name: claude-code | copilot | cursor | codex | unknown>\"\n\nwith open(\".env\", \"w\") as f:\n    f.write(f\"DATAVERSE_URL={dataverse_url}\\n\")\n    f.write(f\"TENANT_ID={tenant_id}\\n\")\n    f.write(f\"MCP_CLIENT_ID={mcp_client_id}\\n\")\n    f.write(f\"DATAVERSE_PLUGIN_VERSION={plugin_version}\\n\")\n    f.write(f\"DATAVERSE_PLUGIN_AGENT={agent_host}\\n\")\n    f.write(f\"SOLUTION_NAME={solution_name}\\n\")\n    f.write(f\"PUBLISHER_PREFIX=\\n\")  # filled in when solution is created\n    f.write(f\"PAC_AUTH_PROFILE=nonprod\\n\")\n    if client_id:\n        f.write(f\"CLIENT_ID={client_id}\\n\")\n    if client_secret:\n        f.write(f\"CLIENT_SECRET={client_secret}\\n\")\n```\n\n> **Multi-environment repos:** If the team deploys to multiple environments from the same repo, each developer's `.env` represents their current target. Consider `.env.dev`, `.env.staging`, etc., with a pattern like `cp .env.dev .env` to switch targets.\n\nEnsure `.env` is in `.gitignore`:\n\n```python\nimport os\n\nGITIGNORE_ENTRIES = [\n    \".env\", \".vscode\u002Fsettings.json\", \".claude\u002Fmcp_settings.json\",\n    \".token_cache.bin\", \"*.snk\", \"__pycache__\u002F\", \"*.pyc\",\n    \"solutions\u002F*.zip\", \"plugins\u002F**\u002Fbin\u002F\", \"plugins\u002F**\u002Fobj\u002F\",\n]\ngitignore = open(\".gitignore\").read() if os.path.exists(\".gitignore\") else \"\"\nmissing = [e for e in GITIGNORE_ENTRIES if e not in gitignore]\nif missing:\n    with open(\".gitignore\", \"a\") as f:\n        f.write(\"\\n\" + \"\\n\".join(missing) + \"\\n\")\n```\n\n**Skip condition:** `.env` already exists with all required values.\n\n---\n\n## Step 4: Set up project structure (new projects only)\n\nIf this is a new project (no `scripts\u002F` directory):\n\n```\nmkdir -p solutions plugins scripts\n```\n\nCopy plugin scripts:\n```\ncp .github\u002Fplugins\u002Fdataverse\u002Fscripts\u002Fauth.py scripts\u002F\n```\n\nCopy `templates\u002FCLAUDE.md` to the repo root if it doesn't exist. Replace placeholders (`{{DATAVERSE_URL}}`, `{{SOLUTION_NAME}}`, `{{PUBLISHER_PREFIX}}`) with values from `.env`.\n\n**Skip condition:** `scripts\u002Fauth.py` exists.\n\n---\n\n## Step 5: Verify the connection\n\n```\ndataverse auth who\npac org who\npython scripts\u002Fauth.py\n```\n\nAll three must resolve the same user\u002Fenvironment. They prove the DV CLI cache, the PAC profile (Step 2b), and Python's silent reuse of the DV CLI cache are all wired.\n\n**If any fail:**\n- `dataverse auth who` fails → re-run Step 2.\n- `pac org who` fails → re-run Step 2b.\n- `python scripts\u002Fauth.py` prints a device-code URL → browser\u002FWAM cache has no Python-reusable token (both exercises hit this). **Auto-fix:** re-run `dataverse auth create --environment \u003Curl> --deviceCode`, then re-run `python scripts\u002Fauth.py`. If it *still* prompts, check `pip show msal msal-extensions` — `auth.py` needs both to read the shared cache.\n- Other Python error → check SDK install and `.env`.\n\nBefore metadata work, also confirm the account has the `prvCreateEntity` customization privilege — see [tools-setup.md](references\u002Ftools-setup.md#privilege-preflight).\n\n---\n\n## Step 6: Configure MCP server\n\n**Skip this step** if MCP is already configured:\n- `.mcp.json` or `~\u002F.copilot\u002Fmcp-config.json` or `~\u002F.cursor\u002Fmcp.json` or `~\u002F.codex\u002Fconfig.toml` contains a Dataverse server entry\n- `claude mcp list` shows a `dataverse-*` server registered\n\nIf MCP is not configured, follow [mcp-configuration.md](references\u002Fmcp-configuration.md):\n\n1. Detect which tool the user is running (Copilot, Claude, Cursor, or Codex) from context\n2. Set `MCP_CLIENT_ID` based on tool choice\n3. Get environment URL from `.env`\n4. Default to GA endpoint (`\u002Fapi\u002Fmcp`)\n5. Register the MCP server per host (see the per-host blocks below)\n6. Handle admin consent and allowlist — prefer `dataverse mcp allow \u003CMCP_CLIENT_ID>` over the portal (one-time per tenant\u002Fenvironment)\n\n**Plugin attribution for MCP:** This plugin uses the **stdio proxy** transport (`npx @microsoft\u002Fdataverse mcp \u003Curl>`) — the CLI runs as a local subprocess and proxies requests to the Dataverse MCP HTTP endpoint. When registering it, include `DATAVERSE_OPERATION_CONTEXT` in the env block so the CLI appends it to its User-Agent on outbound requests to `\u002Fapi\u002Fmcp`. Build the value from `.env`:\n\n```\nDATAVERSE_OPERATION_CONTEXT=app=dataverse-skills\u002F{DATAVERSE_PLUGIN_VERSION};skill=mcp-direct;agent={DATAVERSE_PLUGIN_AGENT}\n```\n\nFor Claude Code (`claude mcp add -t stdio`), pass it via `-e DATAVERSE_OPERATION_CONTEXT=...`. For Copilot\u002FCursor JSON configs, add it to the `\"env\"` object in the stdio server entry; for Codex, add it to its `[mcp_servers.\u003Cname>.env]` table.\n\n**Important:** MCP configuration requires an editor\u002FCLI restart.\n\n**For Copilot:** Write the JSON config, then:\n> ✅ Dataverse MCP server configured. **Restart your editor** for changes to take effect.\n\n**For Claude:** Run the `claude mcp add` command, then warn the user about the auth popup that will appear on next launch:\n> ✅ Dataverse MCP server registered. Restart Claude Code to enable MCP tools.\n> Remember to **use `claude --continue` to resume the session** without losing context.\n>\n> **On restart, a browser window will open** asking you to sign in to your Dataverse environment. This is the MCP proxy authenticating on your behalf — sign in with the same account you used for `dataverse auth create` (or your active DV CLI profile, e.g., `{username}`). This only happens once; the token is cached for future sessions, and `dataverse auth create` populates the same cache so the popup is skipped if you've already run it.\n\n**For Cursor:** Write the JSON config, then:\n> ✅ Dataverse MCP server `dataverse-{orgid}` configured in `~\u002F.cursor\u002Fmcp.json`. **Reload the Cursor window** (Ctrl+Shift+P → \"Developer: Reload Window\") for the new MCP server to appear under Settings → Tools & MCPs.\n>\n> On first use, the `npx @microsoft\u002Fdataverse` proxy starts a device-code sign-in in your browser. Sign in with the same account you used for `dataverse auth create`; the token is cached in your OS credential store for future sessions. If you've already run `dataverse auth create`, the proxy reuses that cache silently — no device code.\n\n**For Codex:** Write the TOML config to `~\u002F.codex\u002Fconfig.toml`. Codex loads MCP tools only at startup, so don't claim they're callable until the user restarts. Tell the user:\n> ✅ Dataverse MCP server `dataverse-{orgid}` configured in `~\u002F.codex\u002Fconfig.toml`. **Restart Codex** (CLI) or reload the Codex IDE to load the MCP tools.\n\n---\n\n## Step 7: Final verification\n\nAfter the editor\u002FCLI restarts, **both** of these must succeed before declaring the setup complete:\n\n**Check 1: `claude mcp list` (or Copilot equivalent) shows ✓ Connected**\n```\nclaude mcp list\n```\nThis proves the MCP server process starts and speaks the MCP protocol. It does NOT by itself prove that data operations work — authentication, environment allowlisting, and endpoint reachability are only exercised on the first real tool call.\n\n**Check 2: Agent successfully lists tables via `describe`\u002F`search` and returns data**\n> \"List the tables in my Dataverse environment.\"\n\nThis proves end-to-end wiring: auth, tenant consent, environment allowlist, and endpoint reachability are all correct. If the agent falls back to PAC CLI or Web API, see [mcp-configuration.md](references\u002Fmcp-configuration.md) troubleshooting.\n\nOnly when **both** checks pass is the setup verified.\n\n**Interpreting failures:**\n\n- If Check 1 fails (server not ✓ Connected): the MCP server itself cannot start. Re-run Step 6 and check that `npx`\u002FNode.js are installed and the MCP registration succeeded.\n- If Check 1 passes but Check 2 fails (server starts but `describe`\u002F`search` errors): the server can speak MCP but cannot reach or read Dataverse. Run `--validate` below to diagnose.\n\n**Diagnostic — `--validate` (for failure investigation only):**\n```\nnpx @microsoft\u002Fdataverse mcp {DATAVERSE_URL} --validate\n```\nThis exercises two Dataverse MCP endpoints with a fresh authentication handshake and reports detailed errors (auth, allowlist, consent, endpoint reachability):\n\n- **GA \u002F Production endpoint** — `{DATAVERSE_URL}\u002Fapi\u002Fmcp`. This is the one the plugin actually uses at runtime.\n- **Preview endpoint** — `{DATAVERSE_URL}\u002Fapi\u002Fmcp_preview`. Opt-in per environment; not used by the plugin.\n\n**Do not use `--validate` as a success gate on first-time setup.** On a freshly configured workspace, the token cache hasn't warmed up, so `--validate` can fail with `MsalClientException` or `403` while MCP is actually working fine on subsequent real calls. Reserve `--validate` for diagnosing a confirmed failure in Check 1 or Check 2.\n\n**How to read `--validate` output:**\n\n- **Look at the GA \u002F Production endpoint (`\u002Fapi\u002Fmcp`) result first.** If this passes, MCP will work for normal plugin usage regardless of what the Preview endpoint reports.\n- **A `403 Forbidden` on the Preview endpoint (`\u002Fapi\u002Fmcp_preview`) is expected for most environments.** Preview is opt-in per environment; if your environment hasn't enabled it, the Preview check will always fail. This does not indicate a broken setup.\n- **Ignore the overall exit code and the `⚠ Partial success` warning in this case.** The validator returns exit code `1` (failure) unless BOTH `\u002Fapi\u002Fmcp` and `\u002Fapi\u002Fmcp_preview` pass. Because most environments don't enable the Preview endpoint, `--validate` will exit `1` even when MCP is fully functional via the GA endpoint. Focus on per-endpoint results, not the aggregate status.\n- **If the GA endpoint (`\u002Fapi\u002Fmcp`) fails:** that's the real signal to investigate — auth, tenant consent, environment allowlist, or endpoint reachability.\n\n### MCP Server Capabilities\n\nFor what MCP can and can't do (data CRUD + batch up to 25, table\u002Fcolumn creation incl. choice\u002Flookup, `search`\u002F`describe`, file upload\u002Fdownload) versus the SDK \u002F Web API, see the **overview** skill's Tool Capabilities matrix.\n\nAfter verifying MCP works, tell the user:\n\n> ✅ Connected to Dataverse at `{DATAVERSE_URL}`. Tools installed, authenticated, MCP live.\n>\n> You can now:\n> - Create tables, columns, and relationships (`dv-metadata`)\n> - Write and import data (`dv-data`)\n> - Query and analyze data (`dv-query`)\n> - Export and promote solutions (`dv-solution`)\n>\n> To create your first solution, see the `dv-solution` skill.\n> To load sample data (accounts, contacts, opportunities), ask: \"Load demo data into my Dataverse environment.\"\n\n---\n\n## Supported Agents\n\nThis plugin's skill files are natively loaded by both **GitHub Copilot CLI** and **Claude Code CLI** when installed as a plugin. No manual context-loading is needed — both agents discover and invoke skills automatically.\n\nThe PAC CLI commands, Python scripts, and XML templates work identically in both environments.\n",{"data":41,"body":42},{"name":4,"description":6},{"type":43,"children":44},"root",[45,54,60,82,99,103,110,132,144,302,327,359,376,379,385,406,587,615,634,639,651,686,691,700,725,728,734,739,802,807,816,831,853,861,869,887,896,901,909,918,928,937,952,960,969,1006,1011,1146,1153,1171,1180,1199,1202,1208,1213,1244,1256,1268,1293,1305,1419,1588,1631,1651,1753,1769,1772,1778,1791,1800,1805,1814,1855,1870,1873,1879,1888,1893,1901,1990,2009,2012,2018,2028,2081,2091,2152,2198,2207,2244,2254,2264,2279,2297,2351,2360,2416,2433,2459,2462,2468,2480,2495,2504,2509,2533,2541,2552,2563,2571,2613,2628,2637,2642,2679,2725,2740,2856,2862,2887,2892,2974,2977,2983,3001,3006],{"type":46,"tag":47,"props":48,"children":50},"element","h1",{"id":49},"skill-connect",[51],{"type":52,"value":53},"text","Skill: Connect",{"type":46,"tag":55,"props":56,"children":57},"p",{},[58],{"type":52,"value":59},"One-step connection to Dataverse. Handles tool installation, authentication, environment selection, workspace initialization, MCP configuration, and verification — all idempotently. Each step checks if it's already done and skips if so.",{"type":46,"tag":61,"props":62,"children":63},"blockquote",{},[64],{"type":46,"tag":55,"props":65,"children":66},{},[67,73,75,80],{"type":46,"tag":68,"props":69,"children":70},"strong",{},[71],{"type":52,"value":72},"Environment-First Rule",{"type":52,"value":74}," — All metadata (solutions, columns, tables, forms, views) and plugin registrations are created ",{"type":46,"tag":68,"props":76,"children":77},{},[78],{"type":52,"value":79},"in the Dynamics environment",{"type":52,"value":81}," via API or scripts, then pulled into the repo. Never write or edit solution XML by hand to create new components.",{"type":46,"tag":55,"props":83,"children":84},{},[85,90,92,97],{"type":46,"tag":68,"props":86,"children":87},{},[88],{"type":52,"value":89},"Execute every step in order.",{"type":52,"value":91}," Do not skip ahead, even if a later step appears more relevant to the user's immediate goal. ",{"type":46,"tag":68,"props":93,"children":94},{},[95],{"type":52,"value":96},"Exception:",{"type":52,"value":98}," Step 0 below can short-circuit the entire flow if the workspace is already set up.",{"type":46,"tag":100,"props":101,"children":102},"hr",{},[],{"type":46,"tag":104,"props":105,"children":107},"h2",{"id":106},"step-0-detect-existing-setup-run-this-first",[108],{"type":52,"value":109},"Step 0: Detect existing setup (run this first)",{"type":46,"tag":55,"props":111,"children":112},{},[113,115,122,124,130],{"type":52,"value":114},"Before touching anything, check whether this workspace is already connected to a Dataverse environment. This matters a lot on ",{"type":46,"tag":116,"props":117,"children":119},"code",{"className":118},[],[120],{"type":52,"value":121},"claude --continue",{"type":52,"value":123}," or any re-run — repeating it on an already-configured workspace overwrites ",{"type":46,"tag":116,"props":125,"children":127},{"className":126},[],[128],{"type":52,"value":129},".env",{"type":52,"value":131},", re-registers MCP, and wastes time.",{"type":46,"tag":55,"props":133,"children":134},{},[135,137,142],{"type":52,"value":136},"Run these checks in order. If ",{"type":46,"tag":68,"props":138,"children":139},{},[140],{"type":52,"value":141},"all four pass",{"type":52,"value":143},", skip straight to Step 7 (final verification) and stop there.",{"type":46,"tag":145,"props":146,"children":147},"ol",{},[148,186,224,285],{"type":46,"tag":149,"props":150,"children":151},"li",{},[152,162,164,170,172,178,180],{"type":46,"tag":68,"props":153,"children":154},{},[155,160],{"type":46,"tag":116,"props":156,"children":158},{"className":157},[],[159],{"type":52,"value":129},{"type":52,"value":161}," is present and complete",{"type":52,"value":163}," — file exists at the workspace root and contains non-empty values for ",{"type":46,"tag":116,"props":165,"children":167},{"className":166},[],[168],{"type":52,"value":169},"DATAVERSE_URL",{"type":52,"value":171},", ",{"type":46,"tag":116,"props":173,"children":175},{"className":174},[],[176],{"type":52,"value":177},"TENANT_ID",{"type":52,"value":179},", and ",{"type":46,"tag":116,"props":181,"children":183},{"className":182},[],[184],{"type":52,"value":185},"MCP_CLIENT_ID",{"type":46,"tag":149,"props":187,"children":188},{},[189,194,196,202,204,210,212,217,219],{"type":46,"tag":68,"props":190,"children":191},{},[192],{"type":52,"value":193},"MCP is registered",{"type":52,"value":195}," — ",{"type":46,"tag":116,"props":197,"children":199},{"className":198},[],[200],{"type":52,"value":201},".mcp.json",{"type":52,"value":203}," (Claude Code) or the equivalent Copilot \u002F Cursor config file has a ",{"type":46,"tag":116,"props":205,"children":207},{"className":206},[],[208],{"type":52,"value":209},"dataverse-*",{"type":52,"value":211}," server entry pointing at the ",{"type":46,"tag":116,"props":213,"children":215},{"className":214},[],[216],{"type":52,"value":169},{"type":52,"value":218}," from ",{"type":46,"tag":116,"props":220,"children":222},{"className":221},[],[223],{"type":52,"value":129},{"type":46,"tag":149,"props":225,"children":226},{},[227,237,238,244,246,252,254,259,261,267,269,275,277,283],{"type":46,"tag":68,"props":228,"children":229},{},[230,232],{"type":52,"value":231},"Both auth surfaces match ",{"type":46,"tag":116,"props":233,"children":235},{"className":234},[],[236],{"type":52,"value":129},{"type":52,"value":195},{"type":46,"tag":116,"props":239,"children":241},{"className":240},[],[242],{"type":52,"value":243},"dataverse auth who",{"type":52,"value":245}," shows a profile whose ",{"type":46,"tag":116,"props":247,"children":249},{"className":248},[],[250],{"type":52,"value":251},"Environment Url",{"type":52,"value":253}," matches ",{"type":46,"tag":116,"props":255,"children":257},{"className":256},[],[258],{"type":52,"value":169},{"type":52,"value":260},", AND ",{"type":46,"tag":116,"props":262,"children":264},{"className":263},[],[265],{"type":52,"value":266},"pac org who",{"type":52,"value":268}," against a PAC profile for the same URL succeeds. (DV CLI auth covers Connect \u002F Data \u002F Query \u002F Metadata \u002F MCP \u002F Python; PAC auth covers ",{"type":46,"tag":116,"props":270,"children":272},{"className":271},[],[273],{"type":52,"value":274},"dv-solution",{"type":52,"value":276}," and ",{"type":46,"tag":116,"props":278,"children":280},{"className":279},[],[281],{"type":52,"value":282},"dv-admin",{"type":52,"value":284},". Both are front-loaded at connect time so neither prompts later.)",{"type":46,"tag":149,"props":286,"children":287},{},[288,293,294,300],{"type":46,"tag":68,"props":289,"children":290},{},[291],{"type":52,"value":292},"Python SDK is importable and current",{"type":52,"value":195},{"type":46,"tag":116,"props":295,"children":297},{"className":296},[],[298],{"type":52,"value":299},"python -c \"from PowerPlatform.Dataverse.client import DataverseClient; import pandas; from importlib.metadata import version; v=version('PowerPlatform-Dataverse-Client'); assert int(v.split('.')[0])>=1, f'SDK {v} is outdated, need >=1.0.0'\"",{"type":52,"value":301}," exits 0",{"type":46,"tag":55,"props":303,"children":304},{},[305,310,312,317,319,325],{"type":46,"tag":68,"props":306,"children":307},{},[308],{"type":52,"value":309},"If all pass:",{"type":52,"value":311}," Tell the user you detected an existing setup, list what you found (URL, profile name, MCP server name), then jump to Step 7. Do not rewrite ",{"type":46,"tag":116,"props":313,"children":315},{"className":314},[],[316],{"type":52,"value":129},{"type":52,"value":318},", do not re-register MCP, do not re-run ",{"type":46,"tag":116,"props":320,"children":322},{"className":321},[],[323],{"type":52,"value":324},"pip install",{"type":52,"value":326},".",{"type":46,"tag":61,"props":328,"children":329},{},[330],{"type":46,"tag":55,"props":331,"children":332},{},[333,335,341,343,349,351,357],{"type":52,"value":334},"Example: \"Detected existing Dataverse setup at ",{"type":46,"tag":116,"props":336,"children":338},{"className":337},[],[339],{"type":52,"value":340},"{DATAVERSE_URL}",{"type":52,"value":342}," (auth profile: ",{"type":46,"tag":116,"props":344,"children":346},{"className":345},[],[347],{"type":52,"value":348},"{PROFILE}",{"type":52,"value":350},", MCP server: ",{"type":46,"tag":116,"props":352,"children":354},{"className":353},[],[355],{"type":52,"value":356},"dataverse-{orgid}",{"type":52,"value":358},"). Running verification only.\"",{"type":46,"tag":55,"props":360,"children":361},{},[362,367,369,374],{"type":46,"tag":68,"props":363,"children":364},{},[365],{"type":52,"value":366},"If any check fails:",{"type":52,"value":368}," Proceed through the normal flow (Steps 1–7), but still use each step's own skip condition. A partially-configured workspace doesn't need a full redo — e.g., if only ",{"type":46,"tag":116,"props":370,"children":372},{"className":371},[],[373],{"type":52,"value":129},{"type":52,"value":375}," and MCP are missing but tools and auth are fine, start at Step 2 or Step 3.",{"type":46,"tag":100,"props":377,"children":378},{},[],{"type":46,"tag":104,"props":380,"children":382},{"id":381},"step-1-ensure-tools-are-installed",[383],{"type":52,"value":384},"Step 1: Ensure tools are installed",{"type":46,"tag":55,"props":386,"children":387},{},[388,390,395,397,404],{"type":52,"value":389},"Check each tool independently — ",{"type":46,"tag":68,"props":391,"children":392},{},[393],{"type":52,"value":394},"do not use fail-fast parallel execution.",{"type":52,"value":396}," If one tool check fails, continue checking the others so you can report all missing tools at once. See ",{"type":46,"tag":398,"props":399,"children":401},"a",{"href":400},"references\u002Ftools-setup.md",[402],{"type":52,"value":403},"tools-setup.md",{"type":52,"value":405}," for installation commands and platform-specific notes.",{"type":46,"tag":407,"props":408,"children":409},"table",{},[410,429],{"type":46,"tag":411,"props":412,"children":413},"thead",{},[414],{"type":46,"tag":415,"props":416,"children":417},"tr",{},[418,424],{"type":46,"tag":419,"props":420,"children":421},"th",{},[422],{"type":52,"value":423},"Tool",{"type":46,"tag":419,"props":425,"children":426},{},[427],{"type":52,"value":428},"Check",{"type":46,"tag":430,"props":431,"children":432},"tbody",{},[433,451,468,485,518,553,570],{"type":46,"tag":415,"props":434,"children":435},{},[436,442],{"type":46,"tag":437,"props":438,"children":439},"td",{},[440],{"type":52,"value":441},"Python 3",{"type":46,"tag":437,"props":443,"children":444},{},[445],{"type":46,"tag":116,"props":446,"children":448},{"className":447},[],[449],{"type":52,"value":450},"python --version",{"type":46,"tag":415,"props":452,"children":453},{},[454,459],{"type":46,"tag":437,"props":455,"children":456},{},[457],{"type":52,"value":458},"Git",{"type":46,"tag":437,"props":460,"children":461},{},[462],{"type":46,"tag":116,"props":463,"children":465},{"className":464},[],[466],{"type":52,"value":467},"git --version",{"type":46,"tag":415,"props":469,"children":470},{},[471,476],{"type":46,"tag":437,"props":472,"children":473},{},[474],{"type":52,"value":475},"Node.js",{"type":46,"tag":437,"props":477,"children":478},{},[479],{"type":46,"tag":116,"props":480,"children":482},{"className":481},[],[483],{"type":52,"value":484},"node --version",{"type":46,"tag":415,"props":486,"children":487},{},[488,493],{"type":46,"tag":437,"props":489,"children":490},{},[491],{"type":52,"value":492},"PAC CLI",{"type":46,"tag":437,"props":494,"children":495},{},[496,502,504,510,512,516],{"type":46,"tag":116,"props":497,"children":499},{"className":498},[],[500],{"type":52,"value":501},"pac",{"type":52,"value":503}," (prints version banner; note: ",{"type":46,"tag":116,"props":505,"children":507},{"className":506},[],[508],{"type":52,"value":509},"pac --version",{"type":52,"value":511}," is not a valid command and returns a non-zero exit code) (see ",{"type":46,"tag":398,"props":513,"children":514},{"href":400},[515],{"type":52,"value":403},{"type":52,"value":517}," for Windows path discovery if not in PATH)",{"type":46,"tag":415,"props":519,"children":520},{},[521,526],{"type":46,"tag":437,"props":522,"children":523},{},[524],{"type":52,"value":525},"Dataverse CLI",{"type":46,"tag":437,"props":527,"children":528},{},[529,535,537,543,545,551],{"type":46,"tag":116,"props":530,"children":532},{"className":531},[],[533],{"type":52,"value":534},"npm list -g @microsoft\u002Fdataverse",{"type":52,"value":536}," (prints ",{"type":46,"tag":116,"props":538,"children":540},{"className":539},[],[541],{"type":52,"value":542},"@microsoft\u002Fdataverse@\u003Cversion>",{"type":52,"value":544}," if installed globally; prints ",{"type":46,"tag":116,"props":546,"children":548},{"className":547},[],[549],{"type":52,"value":550},"(empty)",{"type":52,"value":552}," if not)",{"type":46,"tag":415,"props":554,"children":555},{},[556,561],{"type":46,"tag":437,"props":557,"children":558},{},[559],{"type":52,"value":560},".NET SDK",{"type":46,"tag":437,"props":562,"children":563},{},[564],{"type":46,"tag":116,"props":565,"children":567},{"className":566},[],[568],{"type":52,"value":569},"dotnet --version",{"type":46,"tag":415,"props":571,"children":572},{},[573,578],{"type":46,"tag":437,"props":574,"children":575},{},[576],{"type":52,"value":577},"Azure CLI",{"type":46,"tag":437,"props":579,"children":580},{},[581],{"type":46,"tag":116,"props":582,"children":584},{"className":583},[],[585],{"type":52,"value":586},"az --version",{"type":46,"tag":55,"props":588,"children":589},{},[590,592,598,600,606,608,613],{"type":52,"value":591},".NET SDK is needed for PAC CLI but NOT for the Dataverse CLI (the npm package bundles its own runtime). Node.js powers the Dataverse CLI npm package (",{"type":46,"tag":116,"props":593,"children":595},{"className":594},[],[596],{"type":52,"value":597},"@microsoft\u002Fdataverse",{"type":52,"value":599},"), which is used as the MCP proxy and for scripted data plane actions. Azure CLI is used as a fallback for environment discovery when PAC CLI isn't available (see ",{"type":46,"tag":398,"props":601,"children":603},{"href":602},"references\u002Fmcp-configuration.md",[604],{"type":52,"value":605},"mcp-configuration.md",{"type":52,"value":607}," Step 3b). GitHub CLI is not needed for connecting — it's used later for ALM\u002FCI\u002FCD scenarios (see ",{"type":46,"tag":116,"props":609,"children":611},{"className":610},[],[612],{"type":52,"value":274},{"type":52,"value":614},").",{"type":46,"tag":55,"props":616,"children":617},{},[618,620,624,626,632],{"type":52,"value":619},"If any tool is missing, install it (see ",{"type":46,"tag":398,"props":621,"children":622},{"href":400},[623],{"type":52,"value":403},{"type":52,"value":625},"), then verify. If ",{"type":46,"tag":116,"props":627,"children":629},{"className":628},[],[630],{"type":52,"value":631},"winget",{"type":52,"value":633}," installs a tool but it's not in PATH, ask the user to restart the terminal.",{"type":46,"tag":55,"props":635,"children":636},{},[637],{"type":52,"value":638},"After Python is confirmed:",{"type":46,"tag":640,"props":641,"children":645},"pre",{"className":642,"code":644,"language":52},[643],"language-text","pip install --upgrade azure-identity requests PowerPlatform-Dataverse-Client pandas msal msal-extensions\n",[646],{"type":46,"tag":116,"props":647,"children":649},{"__ignoreMap":648},"",[650],{"type":52,"value":644},{"type":46,"tag":55,"props":652,"children":653},{},[654,660,662,668,670,676,678,684],{"type":46,"tag":116,"props":655,"children":657},{"className":656},[],[658],{"type":52,"value":659},"msal",{"type":52,"value":661}," + ",{"type":46,"tag":116,"props":663,"children":665},{"className":664},[],[666],{"type":52,"value":667},"msal-extensions",{"type":52,"value":669}," let ",{"type":46,"tag":116,"props":671,"children":673},{"className":672},[],[674],{"type":52,"value":675},"scripts\u002Fauth.py",{"type":52,"value":677}," reuse the ",{"type":46,"tag":116,"props":679,"children":681},{"className":680},[],[682],{"type":52,"value":683},"dataverse auth create",{"type":52,"value":685}," cache \\u2014 one sign-in for CLI, MCP, Python.",{"type":46,"tag":55,"props":687,"children":688},{},[689],{"type":52,"value":690},"After Node.js is confirmed, install or upgrade the Dataverse CLI to the latest version (run on each connect to keep it current):",{"type":46,"tag":640,"props":692,"children":695},{"className":693,"code":694,"language":52},[643],"npm install -g @microsoft\u002Fdataverse@latest\n",[696],{"type":46,"tag":116,"props":697,"children":698},{"__ignoreMap":648},[699],{"type":52,"value":694},{"type":46,"tag":55,"props":701,"children":702},{},[703,708,710,716,718,724],{"type":46,"tag":68,"props":704,"children":705},{},[706],{"type":52,"value":707},"Skip condition:",{"type":52,"value":709}," All tools present, Python SDK installed, and ",{"type":46,"tag":116,"props":711,"children":713},{"className":712},[],[714],{"type":52,"value":715},"pandas",{"type":52,"value":717}," importable (",{"type":46,"tag":116,"props":719,"children":721},{"className":720},[],[722],{"type":52,"value":723},"python -c \"import pandas\"",{"type":52,"value":614},{"type":46,"tag":100,"props":726,"children":727},{},[],{"type":46,"tag":104,"props":729,"children":731},{"id":730},"step-2-discover-and-select-the-environment",[732],{"type":52,"value":733},"Step 2: Discover and select the environment",{"type":46,"tag":55,"props":735,"children":736},{},[737],{"type":52,"value":738},"Before asking the user for a URL, check what's already available.",{"type":46,"tag":61,"props":740,"children":741},{},[742,752],{"type":46,"tag":55,"props":743,"children":744},{},[745,750],{"type":46,"tag":68,"props":746,"children":747},{},[748],{"type":52,"value":749},"Auth tool choice.",{"type":52,"value":751}," Two tools, two AAD apps, two caches — front-load both at connect:",{"type":46,"tag":145,"props":753,"children":754},{},[755,776],{"type":46,"tag":149,"props":756,"children":757},{},[758,766,768,774],{"type":46,"tag":68,"props":759,"children":760},{},[761],{"type":46,"tag":116,"props":762,"children":764},{"className":763},[],[765],{"type":52,"value":683},{"type":52,"value":767}," (app ",{"type":46,"tag":116,"props":769,"children":771},{"className":770},[],[772],{"type":52,"value":773},"0c412cc3-…",{"type":52,"value":775},") covers DV CLI + MCP + Python.",{"type":46,"tag":149,"props":777,"children":778},{},[779,788,790,795,796,801],{"type":46,"tag":68,"props":780,"children":781},{},[782],{"type":46,"tag":116,"props":783,"children":785},{"className":784},[],[786],{"type":52,"value":787},"pac auth create",{"type":52,"value":789}," (PAC's own app) covers ",{"type":46,"tag":116,"props":791,"children":793},{"className":792},[],[794],{"type":52,"value":274},{"type":52,"value":661},{"type":46,"tag":116,"props":797,"children":799},{"className":798},[],[800],{"type":52,"value":282},{"type":52,"value":326},{"type":46,"tag":55,"props":803,"children":804},{},[805],{"type":52,"value":806},"Check for an existing DV CLI profile first, then fall back to PAC for environment discovery if needed:",{"type":46,"tag":640,"props":808,"children":811},{"className":809,"code":810,"language":52},[643],"dataverse auth list\ndataverse auth who\npac auth list   # PAC profiles are still useful for env discovery \u002F pac org list\n",[812],{"type":46,"tag":116,"props":813,"children":814},{"__ignoreMap":648},[815],{"type":52,"value":810},{"type":46,"tag":55,"props":817,"children":818},{},[819],{"type":46,"tag":68,"props":820,"children":821},{},[822,824,829],{"type":52,"value":823},"If ",{"type":46,"tag":116,"props":825,"children":827},{"className":826},[],[828],{"type":52,"value":243},{"type":52,"value":830}," shows a profile and its environment matches the user's target:",{"type":46,"tag":832,"props":833,"children":834},"ul",{},[835],{"type":46,"tag":149,"props":836,"children":837},{},[838,840,845,846,851],{"type":52,"value":839},"Reuse it. Set ",{"type":46,"tag":116,"props":841,"children":843},{"className":842},[],[844],{"type":52,"value":169},{"type":52,"value":276},{"type":46,"tag":116,"props":847,"children":849},{"className":848},[],[850],{"type":52,"value":177},{"type":52,"value":852}," from the profile.",{"type":46,"tag":55,"props":854,"children":855},{},[856],{"type":46,"tag":68,"props":857,"children":858},{},[859],{"type":52,"value":860},"If no DV CLI profile exists (or it points at the wrong environment):",{"type":46,"tag":832,"props":862,"children":863},{},[864],{"type":46,"tag":149,"props":865,"children":866},{},[867],{"type":52,"value":868},"Ask: \"Do you want to connect to an existing environment or create a new one?\"",{"type":46,"tag":55,"props":870,"children":871},{},[872,877,879,885],{"type":46,"tag":68,"props":873,"children":874},{},[875],{"type":52,"value":876},"Before selecting, check for tenant\u002Fregion mismatch.",{"type":52,"value":878}," If the target environment URL uses a different region (e.g., ",{"type":46,"tag":116,"props":880,"children":882},{"className":881},[],[883],{"type":52,"value":884},"crm10.dynamics.com",{"type":52,"value":886}," = APAC) than the currently authenticated account's environments, create a new profile for the correct tenant rather than trying to reuse the old one:",{"type":46,"tag":640,"props":888,"children":891},{"className":889,"code":890,"language":52},[643],"dataverse auth create --environment \u003Curl>          # interactive (WAM broker on Windows → no browser tab)\ndataverse auth create --environment \u003Curl> --deviceCode   # headless \u002F remote \u002F SSH\n",[892],{"type":46,"tag":116,"props":893,"children":894},{"__ignoreMap":648},[895],{"type":52,"value":890},{"type":46,"tag":55,"props":897,"children":898},{},[899],{"type":52,"value":900},"If the user hits an admin-consent error, the CLI prints the correct scope-scoped consent URL to share with a tenant admin — do not synthesize one.",{"type":46,"tag":55,"props":902,"children":903},{},[904],{"type":46,"tag":68,"props":905,"children":906},{},[907],{"type":52,"value":908},"To switch between existing DV CLI profiles:",{"type":46,"tag":640,"props":910,"children":913},{"className":911,"code":912,"language":52},[643],"dataverse auth select --name \u003Cprofile-name>\n",[914],{"type":46,"tag":116,"props":915,"children":916},{"__ignoreMap":648},[917],{"type":52,"value":912},{"type":46,"tag":55,"props":919,"children":920},{},[921,926],{"type":46,"tag":68,"props":922,"children":923},{},[924],{"type":52,"value":925},"To create a new environment",{"type":52,"value":927}," (requires admin permissions):",{"type":46,"tag":640,"props":929,"children":932},{"className":930,"code":931,"language":52},[643],"pac admin create --name \"\u003Cname>\" --type \"\u003Ctype>\" --region \"\u003Cregion>\"\n",[933],{"type":46,"tag":116,"props":934,"children":935},{"__ignoreMap":648},[936],{"type":52,"value":931},{"type":46,"tag":55,"props":938,"children":939},{},[940,942,950],{"type":52,"value":941},"If this fails with permissions error, guide the user to ",{"type":46,"tag":398,"props":943,"children":947},{"href":944,"rel":945},"https:\u002F\u002Fadmin.powerplatform.microsoft.com\u002F",[946],"nofollow",[948],{"type":52,"value":949},"Power Platform Admin Center",{"type":52,"value":951}," to create it, then connect.",{"type":46,"tag":55,"props":953,"children":954},{},[955],{"type":46,"tag":68,"props":956,"children":957},{},[958],{"type":52,"value":959},"Confirm connection:",{"type":46,"tag":640,"props":961,"children":964},{"className":962,"code":963,"language":52},[643],"dataverse auth who\ndataverse org who      # or: pac org who\n",[965],{"type":46,"tag":116,"props":966,"children":967},{"__ignoreMap":648},[968],{"type":52,"value":963},{"type":46,"tag":55,"props":970,"children":971},{},[972,974,979,980,985,987,993,995,1005],{"type":52,"value":973},"Parse the output to extract ",{"type":46,"tag":116,"props":975,"children":977},{"className":976},[],[978],{"type":52,"value":169},{"type":52,"value":171},{"type":46,"tag":116,"props":981,"children":983},{"className":982},[],[984],{"type":52,"value":177},{"type":52,"value":986},", and — on ERP-linked envs — ",{"type":46,"tag":116,"props":988,"children":990},{"className":989},[],[991],{"type":52,"value":992},"ERP_URL",{"type":52,"value":994}," (see ",{"type":46,"tag":398,"props":996,"children":998},{"href":997},"references\u002Ferp-detection.md",[999],{"type":46,"tag":116,"props":1000,"children":1002},{"className":1001},[],[1003],{"type":52,"value":1004},"erp-detection.md",{"type":52,"value":614},{"type":46,"tag":55,"props":1007,"children":1008},{},[1009],{"type":52,"value":1010},"If neither command shows a tenant ID, fall back to:",{"type":46,"tag":640,"props":1012,"children":1016},{"className":1013,"code":1014,"language":1015,"meta":648,"style":648},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","curl -sI https:\u002F\u002F\u003Corg>.crm.dynamics.com\u002Fapi\u002Fdata\u002Fv9.2\u002F \\\n  | grep -i \"WWW-Authenticate\" \\\n  | sed -n 's|.*login\\.microsoftonline\\.com\u002F\\([^\u002F]*\\).*|\\1|p'\n","bash",[1017],{"type":46,"tag":116,"props":1018,"children":1019},{"__ignoreMap":648},[1020,1075,1113],{"type":46,"tag":1021,"props":1022,"children":1025},"span",{"class":1023,"line":1024},"line",1,[1026,1032,1038,1043,1049,1054,1060,1065,1070],{"type":46,"tag":1021,"props":1027,"children":1029},{"style":1028},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[1030],{"type":52,"value":1031},"curl",{"type":46,"tag":1021,"props":1033,"children":1035},{"style":1034},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[1036],{"type":52,"value":1037}," -sI",{"type":46,"tag":1021,"props":1039,"children":1040},{"style":1034},[1041],{"type":52,"value":1042}," https:\u002F\u002F",{"type":46,"tag":1021,"props":1044,"children":1046},{"style":1045},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[1047],{"type":52,"value":1048},"\u003C",{"type":46,"tag":1021,"props":1050,"children":1051},{"style":1034},[1052],{"type":52,"value":1053},"or",{"type":46,"tag":1021,"props":1055,"children":1057},{"style":1056},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[1058],{"type":52,"value":1059},"g",{"type":46,"tag":1021,"props":1061,"children":1062},{"style":1045},[1063],{"type":52,"value":1064},">",{"type":46,"tag":1021,"props":1066,"children":1067},{"style":1034},[1068],{"type":52,"value":1069},".crm.dynamics.com\u002Fapi\u002Fdata\u002Fv9.2\u002F",{"type":46,"tag":1021,"props":1071,"children":1072},{"style":1056},[1073],{"type":52,"value":1074}," \\\n",{"type":46,"tag":1021,"props":1076,"children":1078},{"class":1023,"line":1077},2,[1079,1084,1089,1094,1099,1104,1109],{"type":46,"tag":1021,"props":1080,"children":1081},{"style":1045},[1082],{"type":52,"value":1083},"  |",{"type":46,"tag":1021,"props":1085,"children":1086},{"style":1028},[1087],{"type":52,"value":1088}," grep",{"type":46,"tag":1021,"props":1090,"children":1091},{"style":1034},[1092],{"type":52,"value":1093}," -i",{"type":46,"tag":1021,"props":1095,"children":1096},{"style":1045},[1097],{"type":52,"value":1098}," \"",{"type":46,"tag":1021,"props":1100,"children":1101},{"style":1034},[1102],{"type":52,"value":1103},"WWW-Authenticate",{"type":46,"tag":1021,"props":1105,"children":1106},{"style":1045},[1107],{"type":52,"value":1108},"\"",{"type":46,"tag":1021,"props":1110,"children":1111},{"style":1056},[1112],{"type":52,"value":1074},{"type":46,"tag":1021,"props":1114,"children":1116},{"class":1023,"line":1115},3,[1117,1121,1126,1131,1136,1141],{"type":46,"tag":1021,"props":1118,"children":1119},{"style":1045},[1120],{"type":52,"value":1083},{"type":46,"tag":1021,"props":1122,"children":1123},{"style":1028},[1124],{"type":52,"value":1125}," sed",{"type":46,"tag":1021,"props":1127,"children":1128},{"style":1034},[1129],{"type":52,"value":1130}," -n",{"type":46,"tag":1021,"props":1132,"children":1133},{"style":1045},[1134],{"type":52,"value":1135}," '",{"type":46,"tag":1021,"props":1137,"children":1138},{"style":1034},[1139],{"type":52,"value":1140},"s|.*login\\.microsoftonline\\.com\u002F\\([^\u002F]*\\).*|\\1|p",{"type":46,"tag":1021,"props":1142,"children":1143},{"style":1045},[1144],{"type":52,"value":1145},"'\n",{"type":46,"tag":1147,"props":1148,"children":1150},"h3",{"id":1149},"step-2b-front-load-pac-cli-auth-for-the-same-environment",[1151],{"type":52,"value":1152},"Step 2b: Front-load PAC CLI auth for the same environment",{"type":46,"tag":55,"props":1154,"children":1155},{},[1156,1158,1163,1164,1169],{"type":52,"value":1157},"PAC uses its own AAD app, so a separate sign-in is required for ",{"type":46,"tag":116,"props":1159,"children":1161},{"className":1160},[],[1162],{"type":52,"value":274},{"type":52,"value":276},{"type":46,"tag":116,"props":1165,"children":1167},{"className":1166},[],[1168],{"type":52,"value":282},{"type":52,"value":1170},". Do it now — user signs in twice back-to-back, no later surprises.",{"type":46,"tag":640,"props":1172,"children":1175},{"className":1173,"code":1174,"language":52},[643],"pac auth list                                       # skip if a profile for $DATAVERSE_URL exists\npac auth create --name \u003Corgid> --environment \u003CDATAVERSE_URL>\n",[1176],{"type":46,"tag":116,"props":1177,"children":1178},{"__ignoreMap":648},[1179],{"type":52,"value":1174},{"type":46,"tag":55,"props":1181,"children":1182},{},[1183,1185,1190,1192,1197],{"type":52,"value":1184},"Use the same account as Step 2. If PAC CLI is not installed, skip with a note that ",{"type":46,"tag":116,"props":1186,"children":1188},{"className":1187},[],[1189],{"type":52,"value":274},{"type":52,"value":1191}," \u002F ",{"type":46,"tag":116,"props":1193,"children":1195},{"className":1194},[],[1196],{"type":52,"value":282},{"type":52,"value":1198}," will need it later.",{"type":46,"tag":100,"props":1200,"children":1201},{},[],{"type":46,"tag":104,"props":1203,"children":1205},{"id":1204},"step-3-create-env",[1206],{"type":52,"value":1207},"Step 3: Create .env",{"type":46,"tag":55,"props":1209,"children":1210},{},[1211],{"type":52,"value":1212},"Present authentication options:",{"type":46,"tag":61,"props":1214,"children":1215},{},[1216,1221],{"type":46,"tag":55,"props":1217,"children":1218},{},[1219],{"type":52,"value":1220},"How would you like to authenticate with Dataverse?",{"type":46,"tag":145,"props":1222,"children":1223},{},[1224,1234],{"type":46,"tag":149,"props":1225,"children":1226},{},[1227,1232],{"type":46,"tag":68,"props":1228,"children":1229},{},[1230],{"type":52,"value":1231},"Interactive login (recommended)",{"type":52,"value":1233}," — Sign in via browser. No app registration needed. Token stays cached across sessions.",{"type":46,"tag":149,"props":1235,"children":1236},{},[1237,1242],{"type":46,"tag":68,"props":1238,"children":1239},{},[1240],{"type":52,"value":1241},"Service principal (for CI\u002FCD)",{"type":52,"value":1243}," — Uses CLIENT_ID and CLIENT_SECRET from an Azure app registration.",{"type":46,"tag":55,"props":1245,"children":1246},{},[1247,1249,1254],{"type":52,"value":1248},"Write ",{"type":46,"tag":116,"props":1250,"children":1252},{"className":1251},[],[1253],{"type":52,"value":129},{"type":52,"value":1255}," directly — do not instruct the user to create it:",{"type":46,"tag":55,"props":1257,"children":1258},{},[1259,1261,1266],{"type":52,"value":1260},"Detect the current tool (Claude or Copilot) from context and set ",{"type":46,"tag":116,"props":1262,"children":1264},{"className":1263},[],[1265],{"type":52,"value":185},{"type":52,"value":1267}," automatically:",{"type":46,"tag":832,"props":1269,"children":1270},{},[1271,1282],{"type":46,"tag":149,"props":1272,"children":1273},{},[1274,1276],{"type":52,"value":1275},"Claude (CLI or VSCode extension): ",{"type":46,"tag":116,"props":1277,"children":1279},{"className":1278},[],[1280],{"type":52,"value":1281},"0c412cc3-0dd6-449b-987f-05b053db9457",{"type":46,"tag":149,"props":1283,"children":1284},{},[1285,1287],{"type":52,"value":1286},"GitHub Copilot: ",{"type":46,"tag":116,"props":1288,"children":1290},{"className":1289},[],[1291],{"type":52,"value":1292},"aebc6443-996d-45c2-90f0-388ff96faa56",{"type":46,"tag":55,"props":1294,"children":1295},{},[1296,1298,1303],{"type":52,"value":1297},"Also set plugin attribution variables for User-Agent tagging. ",{"type":46,"tag":68,"props":1299,"children":1300},{},[1301],{"type":52,"value":1302},"Fill in the two literals below from your own context",{"type":52,"value":1304}," — you (the agent) loaded this plugin, so you already know both values:",{"type":46,"tag":832,"props":1306,"children":1307},{},[1308,1350],{"type":46,"tag":149,"props":1309,"children":1310},{},[1311,1317,1319,1325,1327,1333,1335,1341,1343,1348],{"type":46,"tag":116,"props":1312,"children":1314},{"className":1313},[],[1315],{"type":52,"value":1316},"PLUGIN_VERSION",{"type":52,"value":1318}," — the ",{"type":46,"tag":116,"props":1320,"children":1322},{"className":1321},[],[1323],{"type":52,"value":1324},"version",{"type":52,"value":1326}," field of your loaded plugin manifest (e.g. ",{"type":46,"tag":116,"props":1328,"children":1330},{"className":1329},[],[1331],{"type":52,"value":1332},"\"1.5.0\"",{"type":52,"value":1334},"). At runtime, ",{"type":46,"tag":116,"props":1336,"children":1338},{"className":1337},[],[1339],{"type":52,"value":1340},"auth.py",{"type":52,"value":1342}," re-reads this from the live manifest via host env vars; this ",{"type":46,"tag":116,"props":1344,"children":1346},{"className":1345},[],[1347],{"type":52,"value":129},{"type":52,"value":1349}," entry is a fallback for offline cases.",{"type":46,"tag":149,"props":1351,"children":1352},{},[1353,1359,1361,1367,1368,1374,1375,1381,1382,1388,1390,1396,1398,1404,1406,1411,1413,1418],{"type":46,"tag":116,"props":1354,"children":1356},{"className":1355},[],[1357],{"type":52,"value":1358},"AGENT",{"type":52,"value":1360}," — your host identity, one of: ",{"type":46,"tag":116,"props":1362,"children":1364},{"className":1363},[],[1365],{"type":52,"value":1366},"claude-code",{"type":52,"value":171},{"type":46,"tag":116,"props":1369,"children":1371},{"className":1370},[],[1372],{"type":52,"value":1373},"copilot",{"type":52,"value":171},{"type":46,"tag":116,"props":1376,"children":1378},{"className":1377},[],[1379],{"type":52,"value":1380},"cursor",{"type":52,"value":171},{"type":46,"tag":116,"props":1383,"children":1385},{"className":1384},[],[1386],{"type":52,"value":1387},"codex",{"type":52,"value":1389},", or ",{"type":46,"tag":116,"props":1391,"children":1393},{"className":1392},[],[1394],{"type":52,"value":1395},"unknown",{"type":52,"value":1397},". Must match an entry in ",{"type":46,"tag":116,"props":1399,"children":1401},{"className":1400},[],[1402],{"type":52,"value":1403},"_ALLOWED_AGENTS",{"type":52,"value":1405}," in ",{"type":46,"tag":116,"props":1407,"children":1409},{"className":1408},[],[1410],{"type":52,"value":1340},{"type":52,"value":1412}," — if you don't recognize your host, use ",{"type":46,"tag":116,"props":1414,"children":1416},{"className":1415},[],[1417],{"type":52,"value":1395},{"type":52,"value":326},{"type":46,"tag":640,"props":1420,"children":1424},{"className":1421,"code":1422,"language":1423,"meta":648,"style":648},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# Substitute these two literals from your loaded plugin context.\n# Do NOT leave the angle-bracket placeholders — replace with real values.\nplugin_version = \"\u003Cplugin manifest version, e.g. 1.5.0>\"\nagent_host = \"\u003Cyour host name: claude-code | copilot | cursor | codex | unknown>\"\n\nwith open(\".env\", \"w\") as f:\n    f.write(f\"DATAVERSE_URL={dataverse_url}\\n\")\n    f.write(f\"TENANT_ID={tenant_id}\\n\")\n    f.write(f\"MCP_CLIENT_ID={mcp_client_id}\\n\")\n    f.write(f\"DATAVERSE_PLUGIN_VERSION={plugin_version}\\n\")\n    f.write(f\"DATAVERSE_PLUGIN_AGENT={agent_host}\\n\")\n    f.write(f\"SOLUTION_NAME={solution_name}\\n\")\n    f.write(f\"PUBLISHER_PREFIX=\\n\")  # filled in when solution is created\n    f.write(f\"PAC_AUTH_PROFILE=nonprod\\n\")\n    if client_id:\n        f.write(f\"CLIENT_ID={client_id}\\n\")\n    if client_secret:\n        f.write(f\"CLIENT_SECRET={client_secret}\\n\")\n","python",[1425],{"type":46,"tag":116,"props":1426,"children":1427},{"__ignoreMap":648},[1428,1436,1444,1452,1461,1471,1480,1489,1498,1507,1516,1525,1534,1543,1552,1561,1570,1579],{"type":46,"tag":1021,"props":1429,"children":1430},{"class":1023,"line":1024},[1431],{"type":46,"tag":1021,"props":1432,"children":1433},{},[1434],{"type":52,"value":1435},"# Substitute these two literals from your loaded plugin context.\n",{"type":46,"tag":1021,"props":1437,"children":1438},{"class":1023,"line":1077},[1439],{"type":46,"tag":1021,"props":1440,"children":1441},{},[1442],{"type":52,"value":1443},"# Do NOT leave the angle-bracket placeholders — replace with real values.\n",{"type":46,"tag":1021,"props":1445,"children":1446},{"class":1023,"line":1115},[1447],{"type":46,"tag":1021,"props":1448,"children":1449},{},[1450],{"type":52,"value":1451},"plugin_version = \"\u003Cplugin manifest version, e.g. 1.5.0>\"\n",{"type":46,"tag":1021,"props":1453,"children":1455},{"class":1023,"line":1454},4,[1456],{"type":46,"tag":1021,"props":1457,"children":1458},{},[1459],{"type":52,"value":1460},"agent_host = \"\u003Cyour host name: claude-code | copilot | cursor | codex | unknown>\"\n",{"type":46,"tag":1021,"props":1462,"children":1464},{"class":1023,"line":1463},5,[1465],{"type":46,"tag":1021,"props":1466,"children":1468},{"emptyLinePlaceholder":1467},true,[1469],{"type":52,"value":1470},"\n",{"type":46,"tag":1021,"props":1472,"children":1474},{"class":1023,"line":1473},6,[1475],{"type":46,"tag":1021,"props":1476,"children":1477},{},[1478],{"type":52,"value":1479},"with open(\".env\", \"w\") as f:\n",{"type":46,"tag":1021,"props":1481,"children":1483},{"class":1023,"line":1482},7,[1484],{"type":46,"tag":1021,"props":1485,"children":1486},{},[1487],{"type":52,"value":1488},"    f.write(f\"DATAVERSE_URL={dataverse_url}\\n\")\n",{"type":46,"tag":1021,"props":1490,"children":1492},{"class":1023,"line":1491},8,[1493],{"type":46,"tag":1021,"props":1494,"children":1495},{},[1496],{"type":52,"value":1497},"    f.write(f\"TENANT_ID={tenant_id}\\n\")\n",{"type":46,"tag":1021,"props":1499,"children":1501},{"class":1023,"line":1500},9,[1502],{"type":46,"tag":1021,"props":1503,"children":1504},{},[1505],{"type":52,"value":1506},"    f.write(f\"MCP_CLIENT_ID={mcp_client_id}\\n\")\n",{"type":46,"tag":1021,"props":1508,"children":1510},{"class":1023,"line":1509},10,[1511],{"type":46,"tag":1021,"props":1512,"children":1513},{},[1514],{"type":52,"value":1515},"    f.write(f\"DATAVERSE_PLUGIN_VERSION={plugin_version}\\n\")\n",{"type":46,"tag":1021,"props":1517,"children":1519},{"class":1023,"line":1518},11,[1520],{"type":46,"tag":1021,"props":1521,"children":1522},{},[1523],{"type":52,"value":1524},"    f.write(f\"DATAVERSE_PLUGIN_AGENT={agent_host}\\n\")\n",{"type":46,"tag":1021,"props":1526,"children":1528},{"class":1023,"line":1527},12,[1529],{"type":46,"tag":1021,"props":1530,"children":1531},{},[1532],{"type":52,"value":1533},"    f.write(f\"SOLUTION_NAME={solution_name}\\n\")\n",{"type":46,"tag":1021,"props":1535,"children":1537},{"class":1023,"line":1536},13,[1538],{"type":46,"tag":1021,"props":1539,"children":1540},{},[1541],{"type":52,"value":1542},"    f.write(f\"PUBLISHER_PREFIX=\\n\")  # filled in when solution is created\n",{"type":46,"tag":1021,"props":1544,"children":1546},{"class":1023,"line":1545},14,[1547],{"type":46,"tag":1021,"props":1548,"children":1549},{},[1550],{"type":52,"value":1551},"    f.write(f\"PAC_AUTH_PROFILE=nonprod\\n\")\n",{"type":46,"tag":1021,"props":1553,"children":1555},{"class":1023,"line":1554},15,[1556],{"type":46,"tag":1021,"props":1557,"children":1558},{},[1559],{"type":52,"value":1560},"    if client_id:\n",{"type":46,"tag":1021,"props":1562,"children":1564},{"class":1023,"line":1563},16,[1565],{"type":46,"tag":1021,"props":1566,"children":1567},{},[1568],{"type":52,"value":1569},"        f.write(f\"CLIENT_ID={client_id}\\n\")\n",{"type":46,"tag":1021,"props":1571,"children":1573},{"class":1023,"line":1572},17,[1574],{"type":46,"tag":1021,"props":1575,"children":1576},{},[1577],{"type":52,"value":1578},"    if client_secret:\n",{"type":46,"tag":1021,"props":1580,"children":1582},{"class":1023,"line":1581},18,[1583],{"type":46,"tag":1021,"props":1584,"children":1585},{},[1586],{"type":52,"value":1587},"        f.write(f\"CLIENT_SECRET={client_secret}\\n\")\n",{"type":46,"tag":61,"props":1589,"children":1590},{},[1591],{"type":46,"tag":55,"props":1592,"children":1593},{},[1594,1599,1601,1606,1608,1614,1615,1621,1623,1629],{"type":46,"tag":68,"props":1595,"children":1596},{},[1597],{"type":52,"value":1598},"Multi-environment repos:",{"type":52,"value":1600}," If the team deploys to multiple environments from the same repo, each developer's ",{"type":46,"tag":116,"props":1602,"children":1604},{"className":1603},[],[1605],{"type":52,"value":129},{"type":52,"value":1607}," represents their current target. Consider ",{"type":46,"tag":116,"props":1609,"children":1611},{"className":1610},[],[1612],{"type":52,"value":1613},".env.dev",{"type":52,"value":171},{"type":46,"tag":116,"props":1616,"children":1618},{"className":1617},[],[1619],{"type":52,"value":1620},".env.staging",{"type":52,"value":1622},", etc., with a pattern like ",{"type":46,"tag":116,"props":1624,"children":1626},{"className":1625},[],[1627],{"type":52,"value":1628},"cp .env.dev .env",{"type":52,"value":1630}," to switch targets.",{"type":46,"tag":55,"props":1632,"children":1633},{},[1634,1636,1641,1643,1649],{"type":52,"value":1635},"Ensure ",{"type":46,"tag":116,"props":1637,"children":1639},{"className":1638},[],[1640],{"type":52,"value":129},{"type":52,"value":1642}," is in ",{"type":46,"tag":116,"props":1644,"children":1646},{"className":1645},[],[1647],{"type":52,"value":1648},".gitignore",{"type":52,"value":1650},":",{"type":46,"tag":640,"props":1652,"children":1654},{"className":1421,"code":1653,"language":1423,"meta":648,"style":648},"import os\n\nGITIGNORE_ENTRIES = [\n    \".env\", \".vscode\u002Fsettings.json\", \".claude\u002Fmcp_settings.json\",\n    \".token_cache.bin\", \"*.snk\", \"__pycache__\u002F\", \"*.pyc\",\n    \"solutions\u002F*.zip\", \"plugins\u002F**\u002Fbin\u002F\", \"plugins\u002F**\u002Fobj\u002F\",\n]\ngitignore = open(\".gitignore\").read() if os.path.exists(\".gitignore\") else \"\"\nmissing = [e for e in GITIGNORE_ENTRIES if e not in gitignore]\nif missing:\n    with open(\".gitignore\", \"a\") as f:\n        f.write(\"\\n\" + \"\\n\".join(missing) + \"\\n\")\n",[1655],{"type":46,"tag":116,"props":1656,"children":1657},{"__ignoreMap":648},[1658,1666,1673,1681,1689,1697,1705,1713,1721,1729,1737,1745],{"type":46,"tag":1021,"props":1659,"children":1660},{"class":1023,"line":1024},[1661],{"type":46,"tag":1021,"props":1662,"children":1663},{},[1664],{"type":52,"value":1665},"import os\n",{"type":46,"tag":1021,"props":1667,"children":1668},{"class":1023,"line":1077},[1669],{"type":46,"tag":1021,"props":1670,"children":1671},{"emptyLinePlaceholder":1467},[1672],{"type":52,"value":1470},{"type":46,"tag":1021,"props":1674,"children":1675},{"class":1023,"line":1115},[1676],{"type":46,"tag":1021,"props":1677,"children":1678},{},[1679],{"type":52,"value":1680},"GITIGNORE_ENTRIES = [\n",{"type":46,"tag":1021,"props":1682,"children":1683},{"class":1023,"line":1454},[1684],{"type":46,"tag":1021,"props":1685,"children":1686},{},[1687],{"type":52,"value":1688},"    \".env\", \".vscode\u002Fsettings.json\", \".claude\u002Fmcp_settings.json\",\n",{"type":46,"tag":1021,"props":1690,"children":1691},{"class":1023,"line":1463},[1692],{"type":46,"tag":1021,"props":1693,"children":1694},{},[1695],{"type":52,"value":1696},"    \".token_cache.bin\", \"*.snk\", \"__pycache__\u002F\", \"*.pyc\",\n",{"type":46,"tag":1021,"props":1698,"children":1699},{"class":1023,"line":1473},[1700],{"type":46,"tag":1021,"props":1701,"children":1702},{},[1703],{"type":52,"value":1704},"    \"solutions\u002F*.zip\", \"plugins\u002F**\u002Fbin\u002F\", \"plugins\u002F**\u002Fobj\u002F\",\n",{"type":46,"tag":1021,"props":1706,"children":1707},{"class":1023,"line":1482},[1708],{"type":46,"tag":1021,"props":1709,"children":1710},{},[1711],{"type":52,"value":1712},"]\n",{"type":46,"tag":1021,"props":1714,"children":1715},{"class":1023,"line":1491},[1716],{"type":46,"tag":1021,"props":1717,"children":1718},{},[1719],{"type":52,"value":1720},"gitignore = open(\".gitignore\").read() if os.path.exists(\".gitignore\") else \"\"\n",{"type":46,"tag":1021,"props":1722,"children":1723},{"class":1023,"line":1500},[1724],{"type":46,"tag":1021,"props":1725,"children":1726},{},[1727],{"type":52,"value":1728},"missing = [e for e in GITIGNORE_ENTRIES if e not in gitignore]\n",{"type":46,"tag":1021,"props":1730,"children":1731},{"class":1023,"line":1509},[1732],{"type":46,"tag":1021,"props":1733,"children":1734},{},[1735],{"type":52,"value":1736},"if missing:\n",{"type":46,"tag":1021,"props":1738,"children":1739},{"class":1023,"line":1518},[1740],{"type":46,"tag":1021,"props":1741,"children":1742},{},[1743],{"type":52,"value":1744},"    with open(\".gitignore\", \"a\") as f:\n",{"type":46,"tag":1021,"props":1746,"children":1747},{"class":1023,"line":1527},[1748],{"type":46,"tag":1021,"props":1749,"children":1750},{},[1751],{"type":52,"value":1752},"        f.write(\"\\n\" + \"\\n\".join(missing) + \"\\n\")\n",{"type":46,"tag":55,"props":1754,"children":1755},{},[1756,1760,1762,1767],{"type":46,"tag":68,"props":1757,"children":1758},{},[1759],{"type":52,"value":707},{"type":52,"value":1761}," ",{"type":46,"tag":116,"props":1763,"children":1765},{"className":1764},[],[1766],{"type":52,"value":129},{"type":52,"value":1768}," already exists with all required values.",{"type":46,"tag":100,"props":1770,"children":1771},{},[],{"type":46,"tag":104,"props":1773,"children":1775},{"id":1774},"step-4-set-up-project-structure-new-projects-only",[1776],{"type":52,"value":1777},"Step 4: Set up project structure (new projects only)",{"type":46,"tag":55,"props":1779,"children":1780},{},[1781,1783,1789],{"type":52,"value":1782},"If this is a new project (no ",{"type":46,"tag":116,"props":1784,"children":1786},{"className":1785},[],[1787],{"type":52,"value":1788},"scripts\u002F",{"type":52,"value":1790}," directory):",{"type":46,"tag":640,"props":1792,"children":1795},{"className":1793,"code":1794,"language":52},[643],"mkdir -p solutions plugins scripts\n",[1796],{"type":46,"tag":116,"props":1797,"children":1798},{"__ignoreMap":648},[1799],{"type":52,"value":1794},{"type":46,"tag":55,"props":1801,"children":1802},{},[1803],{"type":52,"value":1804},"Copy plugin scripts:",{"type":46,"tag":640,"props":1806,"children":1809},{"className":1807,"code":1808,"language":52},[643],"cp .github\u002Fplugins\u002Fdataverse\u002Fscripts\u002Fauth.py scripts\u002F\n",[1810],{"type":46,"tag":116,"props":1811,"children":1812},{"__ignoreMap":648},[1813],{"type":52,"value":1808},{"type":46,"tag":55,"props":1815,"children":1816},{},[1817,1819,1825,1827,1833,1834,1840,1841,1847,1849,1854],{"type":52,"value":1818},"Copy ",{"type":46,"tag":116,"props":1820,"children":1822},{"className":1821},[],[1823],{"type":52,"value":1824},"templates\u002FCLAUDE.md",{"type":52,"value":1826}," to the repo root if it doesn't exist. Replace placeholders (",{"type":46,"tag":116,"props":1828,"children":1830},{"className":1829},[],[1831],{"type":52,"value":1832},"{{DATAVERSE_URL}}",{"type":52,"value":171},{"type":46,"tag":116,"props":1835,"children":1837},{"className":1836},[],[1838],{"type":52,"value":1839},"{{SOLUTION_NAME}}",{"type":52,"value":171},{"type":46,"tag":116,"props":1842,"children":1844},{"className":1843},[],[1845],{"type":52,"value":1846},"{{PUBLISHER_PREFIX}}",{"type":52,"value":1848},") with values from ",{"type":46,"tag":116,"props":1850,"children":1852},{"className":1851},[],[1853],{"type":52,"value":129},{"type":52,"value":326},{"type":46,"tag":55,"props":1856,"children":1857},{},[1858,1862,1863,1868],{"type":46,"tag":68,"props":1859,"children":1860},{},[1861],{"type":52,"value":707},{"type":52,"value":1761},{"type":46,"tag":116,"props":1864,"children":1866},{"className":1865},[],[1867],{"type":52,"value":675},{"type":52,"value":1869}," exists.",{"type":46,"tag":100,"props":1871,"children":1872},{},[],{"type":46,"tag":104,"props":1874,"children":1876},{"id":1875},"step-5-verify-the-connection",[1877],{"type":52,"value":1878},"Step 5: Verify the connection",{"type":46,"tag":640,"props":1880,"children":1883},{"className":1881,"code":1882,"language":52},[643],"dataverse auth who\npac org who\npython scripts\u002Fauth.py\n",[1884],{"type":46,"tag":116,"props":1885,"children":1886},{"__ignoreMap":648},[1887],{"type":52,"value":1882},{"type":46,"tag":55,"props":1889,"children":1890},{},[1891],{"type":52,"value":1892},"All three must resolve the same user\u002Fenvironment. They prove the DV CLI cache, the PAC profile (Step 2b), and Python's silent reuse of the DV CLI cache are all wired.",{"type":46,"tag":55,"props":1894,"children":1895},{},[1896],{"type":46,"tag":68,"props":1897,"children":1898},{},[1899],{"type":52,"value":1900},"If any fail:",{"type":46,"tag":832,"props":1902,"children":1903},{},[1904,1914,1924,1979],{"type":46,"tag":149,"props":1905,"children":1906},{},[1907,1912],{"type":46,"tag":116,"props":1908,"children":1910},{"className":1909},[],[1911],{"type":52,"value":243},{"type":52,"value":1913}," fails → re-run Step 2.",{"type":46,"tag":149,"props":1915,"children":1916},{},[1917,1922],{"type":46,"tag":116,"props":1918,"children":1920},{"className":1919},[],[1921],{"type":52,"value":266},{"type":52,"value":1923}," fails → re-run Step 2b.",{"type":46,"tag":149,"props":1925,"children":1926},{},[1927,1933,1935,1940,1942,1948,1950,1955,1957,1963,1965,1971,1972,1977],{"type":46,"tag":116,"props":1928,"children":1930},{"className":1929},[],[1931],{"type":52,"value":1932},"python scripts\u002Fauth.py",{"type":52,"value":1934}," prints a device-code URL → browser\u002FWAM cache has no Python-reusable token (both exercises hit this). ",{"type":46,"tag":68,"props":1936,"children":1937},{},[1938],{"type":52,"value":1939},"Auto-fix:",{"type":52,"value":1941}," re-run ",{"type":46,"tag":116,"props":1943,"children":1945},{"className":1944},[],[1946],{"type":52,"value":1947},"dataverse auth create --environment \u003Curl> --deviceCode",{"type":52,"value":1949},", then re-run ",{"type":46,"tag":116,"props":1951,"children":1953},{"className":1952},[],[1954],{"type":52,"value":1932},{"type":52,"value":1956},". If it ",{"type":46,"tag":1958,"props":1959,"children":1960},"em",{},[1961],{"type":52,"value":1962},"still",{"type":52,"value":1964}," prompts, check ",{"type":46,"tag":116,"props":1966,"children":1968},{"className":1967},[],[1969],{"type":52,"value":1970},"pip show msal msal-extensions",{"type":52,"value":195},{"type":46,"tag":116,"props":1973,"children":1975},{"className":1974},[],[1976],{"type":52,"value":1340},{"type":52,"value":1978}," needs both to read the shared cache.",{"type":46,"tag":149,"props":1980,"children":1981},{},[1982,1984,1989],{"type":52,"value":1983},"Other Python error → check SDK install and ",{"type":46,"tag":116,"props":1985,"children":1987},{"className":1986},[],[1988],{"type":52,"value":129},{"type":52,"value":326},{"type":46,"tag":55,"props":1991,"children":1992},{},[1993,1995,2001,2003,2008],{"type":52,"value":1994},"Before metadata work, also confirm the account has the ",{"type":46,"tag":116,"props":1996,"children":1998},{"className":1997},[],[1999],{"type":52,"value":2000},"prvCreateEntity",{"type":52,"value":2002}," customization privilege — see ",{"type":46,"tag":398,"props":2004,"children":2006},{"href":2005},"references\u002Ftools-setup.md#privilege-preflight",[2007],{"type":52,"value":403},{"type":52,"value":326},{"type":46,"tag":100,"props":2010,"children":2011},{},[],{"type":46,"tag":104,"props":2013,"children":2015},{"id":2014},"step-6-configure-mcp-server",[2016],{"type":52,"value":2017},"Step 6: Configure MCP server",{"type":46,"tag":55,"props":2019,"children":2020},{},[2021,2026],{"type":46,"tag":68,"props":2022,"children":2023},{},[2024],{"type":52,"value":2025},"Skip this step",{"type":52,"value":2027}," if MCP is already configured:",{"type":46,"tag":832,"props":2029,"children":2030},{},[2031,2063],{"type":46,"tag":149,"props":2032,"children":2033},{},[2034,2039,2041,2047,2048,2054,2055,2061],{"type":46,"tag":116,"props":2035,"children":2037},{"className":2036},[],[2038],{"type":52,"value":201},{"type":52,"value":2040}," or ",{"type":46,"tag":116,"props":2042,"children":2044},{"className":2043},[],[2045],{"type":52,"value":2046},"~\u002F.copilot\u002Fmcp-config.json",{"type":52,"value":2040},{"type":46,"tag":116,"props":2049,"children":2051},{"className":2050},[],[2052],{"type":52,"value":2053},"~\u002F.cursor\u002Fmcp.json",{"type":52,"value":2040},{"type":46,"tag":116,"props":2056,"children":2058},{"className":2057},[],[2059],{"type":52,"value":2060},"~\u002F.codex\u002Fconfig.toml",{"type":52,"value":2062}," contains a Dataverse server entry",{"type":46,"tag":149,"props":2064,"children":2065},{},[2066,2072,2074,2079],{"type":46,"tag":116,"props":2067,"children":2069},{"className":2068},[],[2070],{"type":52,"value":2071},"claude mcp list",{"type":52,"value":2073}," shows a ",{"type":46,"tag":116,"props":2075,"children":2077},{"className":2076},[],[2078],{"type":52,"value":209},{"type":52,"value":2080}," server registered",{"type":46,"tag":55,"props":2082,"children":2083},{},[2084,2086,2090],{"type":52,"value":2085},"If MCP is not configured, follow ",{"type":46,"tag":398,"props":2087,"children":2088},{"href":602},[2089],{"type":52,"value":605},{"type":52,"value":1650},{"type":46,"tag":145,"props":2092,"children":2093},{},[2094,2099,2111,2121,2134,2139],{"type":46,"tag":149,"props":2095,"children":2096},{},[2097],{"type":52,"value":2098},"Detect which tool the user is running (Copilot, Claude, Cursor, or Codex) from context",{"type":46,"tag":149,"props":2100,"children":2101},{},[2102,2104,2109],{"type":52,"value":2103},"Set ",{"type":46,"tag":116,"props":2105,"children":2107},{"className":2106},[],[2108],{"type":52,"value":185},{"type":52,"value":2110}," based on tool choice",{"type":46,"tag":149,"props":2112,"children":2113},{},[2114,2116],{"type":52,"value":2115},"Get environment URL from ",{"type":46,"tag":116,"props":2117,"children":2119},{"className":2118},[],[2120],{"type":52,"value":129},{"type":46,"tag":149,"props":2122,"children":2123},{},[2124,2126,2132],{"type":52,"value":2125},"Default to GA endpoint (",{"type":46,"tag":116,"props":2127,"children":2129},{"className":2128},[],[2130],{"type":52,"value":2131},"\u002Fapi\u002Fmcp",{"type":52,"value":2133},")",{"type":46,"tag":149,"props":2135,"children":2136},{},[2137],{"type":52,"value":2138},"Register the MCP server per host (see the per-host blocks below)",{"type":46,"tag":149,"props":2140,"children":2141},{},[2142,2144,2150],{"type":52,"value":2143},"Handle admin consent and allowlist — prefer ",{"type":46,"tag":116,"props":2145,"children":2147},{"className":2146},[],[2148],{"type":52,"value":2149},"dataverse mcp allow \u003CMCP_CLIENT_ID>",{"type":52,"value":2151}," over the portal (one-time per tenant\u002Fenvironment)",{"type":46,"tag":55,"props":2153,"children":2154},{},[2155,2160,2162,2167,2169,2175,2177,2183,2185,2190,2192,2197],{"type":46,"tag":68,"props":2156,"children":2157},{},[2158],{"type":52,"value":2159},"Plugin attribution for MCP:",{"type":52,"value":2161}," This plugin uses the ",{"type":46,"tag":68,"props":2163,"children":2164},{},[2165],{"type":52,"value":2166},"stdio proxy",{"type":52,"value":2168}," transport (",{"type":46,"tag":116,"props":2170,"children":2172},{"className":2171},[],[2173],{"type":52,"value":2174},"npx @microsoft\u002Fdataverse mcp \u003Curl>",{"type":52,"value":2176},") — the CLI runs as a local subprocess and proxies requests to the Dataverse MCP HTTP endpoint. When registering it, include ",{"type":46,"tag":116,"props":2178,"children":2180},{"className":2179},[],[2181],{"type":52,"value":2182},"DATAVERSE_OPERATION_CONTEXT",{"type":52,"value":2184}," in the env block so the CLI appends it to its User-Agent on outbound requests to ",{"type":46,"tag":116,"props":2186,"children":2188},{"className":2187},[],[2189],{"type":52,"value":2131},{"type":52,"value":2191},". Build the value from ",{"type":46,"tag":116,"props":2193,"children":2195},{"className":2194},[],[2196],{"type":52,"value":129},{"type":52,"value":1650},{"type":46,"tag":640,"props":2199,"children":2202},{"className":2200,"code":2201,"language":52},[643],"DATAVERSE_OPERATION_CONTEXT=app=dataverse-skills\u002F{DATAVERSE_PLUGIN_VERSION};skill=mcp-direct;agent={DATAVERSE_PLUGIN_AGENT}\n",[2203],{"type":46,"tag":116,"props":2204,"children":2205},{"__ignoreMap":648},[2206],{"type":52,"value":2201},{"type":46,"tag":55,"props":2208,"children":2209},{},[2210,2212,2218,2220,2226,2228,2234,2236,2242],{"type":52,"value":2211},"For Claude Code (",{"type":46,"tag":116,"props":2213,"children":2215},{"className":2214},[],[2216],{"type":52,"value":2217},"claude mcp add -t stdio",{"type":52,"value":2219},"), pass it via ",{"type":46,"tag":116,"props":2221,"children":2223},{"className":2222},[],[2224],{"type":52,"value":2225},"-e DATAVERSE_OPERATION_CONTEXT=...",{"type":52,"value":2227},". For Copilot\u002FCursor JSON configs, add it to the ",{"type":46,"tag":116,"props":2229,"children":2231},{"className":2230},[],[2232],{"type":52,"value":2233},"\"env\"",{"type":52,"value":2235}," object in the stdio server entry; for Codex, add it to its ",{"type":46,"tag":116,"props":2237,"children":2239},{"className":2238},[],[2240],{"type":52,"value":2241},"[mcp_servers.\u003Cname>.env]",{"type":52,"value":2243}," table.",{"type":46,"tag":55,"props":2245,"children":2246},{},[2247,2252],{"type":46,"tag":68,"props":2248,"children":2249},{},[2250],{"type":52,"value":2251},"Important:",{"type":52,"value":2253}," MCP configuration requires an editor\u002FCLI restart.",{"type":46,"tag":55,"props":2255,"children":2256},{},[2257,2262],{"type":46,"tag":68,"props":2258,"children":2259},{},[2260],{"type":52,"value":2261},"For Copilot:",{"type":52,"value":2263}," Write the JSON config, then:",{"type":46,"tag":61,"props":2265,"children":2266},{},[2267],{"type":46,"tag":55,"props":2268,"children":2269},{},[2270,2272,2277],{"type":52,"value":2271},"✅ Dataverse MCP server configured. ",{"type":46,"tag":68,"props":2273,"children":2274},{},[2275],{"type":52,"value":2276},"Restart your editor",{"type":52,"value":2278}," for changes to take effect.",{"type":46,"tag":55,"props":2280,"children":2281},{},[2282,2287,2289,2295],{"type":46,"tag":68,"props":2283,"children":2284},{},[2285],{"type":52,"value":2286},"For Claude:",{"type":52,"value":2288}," Run the ",{"type":46,"tag":116,"props":2290,"children":2292},{"className":2291},[],[2293],{"type":52,"value":2294},"claude mcp add",{"type":52,"value":2296}," command, then warn the user about the auth popup that will appear on next launch:",{"type":46,"tag":61,"props":2298,"children":2299},{},[2300,2319],{"type":46,"tag":55,"props":2301,"children":2302},{},[2303,2305,2317],{"type":52,"value":2304},"✅ Dataverse MCP server registered. Restart Claude Code to enable MCP tools.\nRemember to ",{"type":46,"tag":68,"props":2306,"children":2307},{},[2308,2310,2315],{"type":52,"value":2309},"use ",{"type":46,"tag":116,"props":2311,"children":2313},{"className":2312},[],[2314],{"type":52,"value":121},{"type":52,"value":2316}," to resume the session",{"type":52,"value":2318}," without losing context.",{"type":46,"tag":55,"props":2320,"children":2321},{},[2322,2327,2329,2334,2336,2342,2344,2349],{"type":46,"tag":68,"props":2323,"children":2324},{},[2325],{"type":52,"value":2326},"On restart, a browser window will open",{"type":52,"value":2328}," asking you to sign in to your Dataverse environment. This is the MCP proxy authenticating on your behalf — sign in with the same account you used for ",{"type":46,"tag":116,"props":2330,"children":2332},{"className":2331},[],[2333],{"type":52,"value":683},{"type":52,"value":2335}," (or your active DV CLI profile, e.g., ",{"type":46,"tag":116,"props":2337,"children":2339},{"className":2338},[],[2340],{"type":52,"value":2341},"{username}",{"type":52,"value":2343},"). This only happens once; the token is cached for future sessions, and ",{"type":46,"tag":116,"props":2345,"children":2347},{"className":2346},[],[2348],{"type":52,"value":683},{"type":52,"value":2350}," populates the same cache so the popup is skipped if you've already run it.",{"type":46,"tag":55,"props":2352,"children":2353},{},[2354,2359],{"type":46,"tag":68,"props":2355,"children":2356},{},[2357],{"type":52,"value":2358},"For Cursor:",{"type":52,"value":2263},{"type":46,"tag":61,"props":2361,"children":2362},{},[2363,2389],{"type":46,"tag":55,"props":2364,"children":2365},{},[2366,2368,2373,2375,2380,2382,2387],{"type":52,"value":2367},"✅ Dataverse MCP server ",{"type":46,"tag":116,"props":2369,"children":2371},{"className":2370},[],[2372],{"type":52,"value":356},{"type":52,"value":2374}," configured in ",{"type":46,"tag":116,"props":2376,"children":2378},{"className":2377},[],[2379],{"type":52,"value":2053},{"type":52,"value":2381},". ",{"type":46,"tag":68,"props":2383,"children":2384},{},[2385],{"type":52,"value":2386},"Reload the Cursor window",{"type":52,"value":2388}," (Ctrl+Shift+P → \"Developer: Reload Window\") for the new MCP server to appear under Settings → Tools & MCPs.",{"type":46,"tag":55,"props":2390,"children":2391},{},[2392,2394,2400,2402,2407,2409,2414],{"type":52,"value":2393},"On first use, the ",{"type":46,"tag":116,"props":2395,"children":2397},{"className":2396},[],[2398],{"type":52,"value":2399},"npx @microsoft\u002Fdataverse",{"type":52,"value":2401}," proxy starts a device-code sign-in in your browser. Sign in with the same account you used for ",{"type":46,"tag":116,"props":2403,"children":2405},{"className":2404},[],[2406],{"type":52,"value":683},{"type":52,"value":2408},"; the token is cached in your OS credential store for future sessions. If you've already run ",{"type":46,"tag":116,"props":2410,"children":2412},{"className":2411},[],[2413],{"type":52,"value":683},{"type":52,"value":2415},", the proxy reuses that cache silently — no device code.",{"type":46,"tag":55,"props":2417,"children":2418},{},[2419,2424,2426,2431],{"type":46,"tag":68,"props":2420,"children":2421},{},[2422],{"type":52,"value":2423},"For Codex:",{"type":52,"value":2425}," Write the TOML config to ",{"type":46,"tag":116,"props":2427,"children":2429},{"className":2428},[],[2430],{"type":52,"value":2060},{"type":52,"value":2432},". Codex loads MCP tools only at startup, so don't claim they're callable until the user restarts. Tell the user:",{"type":46,"tag":61,"props":2434,"children":2435},{},[2436],{"type":46,"tag":55,"props":2437,"children":2438},{},[2439,2440,2445,2446,2451,2452,2457],{"type":52,"value":2367},{"type":46,"tag":116,"props":2441,"children":2443},{"className":2442},[],[2444],{"type":52,"value":356},{"type":52,"value":2374},{"type":46,"tag":116,"props":2447,"children":2449},{"className":2448},[],[2450],{"type":52,"value":2060},{"type":52,"value":2381},{"type":46,"tag":68,"props":2453,"children":2454},{},[2455],{"type":52,"value":2456},"Restart Codex",{"type":52,"value":2458}," (CLI) or reload the Codex IDE to load the MCP tools.",{"type":46,"tag":100,"props":2460,"children":2461},{},[],{"type":46,"tag":104,"props":2463,"children":2465},{"id":2464},"step-7-final-verification",[2466],{"type":52,"value":2467},"Step 7: Final verification",{"type":46,"tag":55,"props":2469,"children":2470},{},[2471,2473,2478],{"type":52,"value":2472},"After the editor\u002FCLI restarts, ",{"type":46,"tag":68,"props":2474,"children":2475},{},[2476],{"type":52,"value":2477},"both",{"type":52,"value":2479}," of these must succeed before declaring the setup complete:",{"type":46,"tag":55,"props":2481,"children":2482},{},[2483],{"type":46,"tag":68,"props":2484,"children":2485},{},[2486,2488,2493],{"type":52,"value":2487},"Check 1: ",{"type":46,"tag":116,"props":2489,"children":2491},{"className":2490},[],[2492],{"type":52,"value":2071},{"type":52,"value":2494}," (or Copilot equivalent) shows ✓ Connected",{"type":46,"tag":640,"props":2496,"children":2499},{"className":2497,"code":2498,"language":52},[643],"claude mcp list\n",[2500],{"type":46,"tag":116,"props":2501,"children":2502},{"__ignoreMap":648},[2503],{"type":52,"value":2498},{"type":46,"tag":55,"props":2505,"children":2506},{},[2507],{"type":52,"value":2508},"This proves the MCP server process starts and speaks the MCP protocol. It does NOT by itself prove that data operations work — authentication, environment allowlisting, and endpoint reachability are only exercised on the first real tool call.",{"type":46,"tag":55,"props":2510,"children":2511},{},[2512],{"type":46,"tag":68,"props":2513,"children":2514},{},[2515,2517,2523,2525,2531],{"type":52,"value":2516},"Check 2: Agent successfully lists tables via ",{"type":46,"tag":116,"props":2518,"children":2520},{"className":2519},[],[2521],{"type":52,"value":2522},"describe",{"type":52,"value":2524},"\u002F",{"type":46,"tag":116,"props":2526,"children":2528},{"className":2527},[],[2529],{"type":52,"value":2530},"search",{"type":52,"value":2532}," and returns data",{"type":46,"tag":61,"props":2534,"children":2535},{},[2536],{"type":46,"tag":55,"props":2537,"children":2538},{},[2539],{"type":52,"value":2540},"\"List the tables in my Dataverse environment.\"",{"type":46,"tag":55,"props":2542,"children":2543},{},[2544,2546,2550],{"type":52,"value":2545},"This proves end-to-end wiring: auth, tenant consent, environment allowlist, and endpoint reachability are all correct. If the agent falls back to PAC CLI or Web API, see ",{"type":46,"tag":398,"props":2547,"children":2548},{"href":602},[2549],{"type":52,"value":605},{"type":52,"value":2551}," troubleshooting.",{"type":46,"tag":55,"props":2553,"children":2554},{},[2555,2557,2561],{"type":52,"value":2556},"Only when ",{"type":46,"tag":68,"props":2558,"children":2559},{},[2560],{"type":52,"value":2477},{"type":52,"value":2562}," checks pass is the setup verified.",{"type":46,"tag":55,"props":2564,"children":2565},{},[2566],{"type":46,"tag":68,"props":2567,"children":2568},{},[2569],{"type":52,"value":2570},"Interpreting failures:",{"type":46,"tag":832,"props":2572,"children":2573},{},[2574,2587],{"type":46,"tag":149,"props":2575,"children":2576},{},[2577,2579,2585],{"type":52,"value":2578},"If Check 1 fails (server not ✓ Connected): the MCP server itself cannot start. Re-run Step 6 and check that ",{"type":46,"tag":116,"props":2580,"children":2582},{"className":2581},[],[2583],{"type":52,"value":2584},"npx",{"type":52,"value":2586},"\u002FNode.js are installed and the MCP registration succeeded.",{"type":46,"tag":149,"props":2588,"children":2589},{},[2590,2592,2597,2598,2603,2605,2611],{"type":52,"value":2591},"If Check 1 passes but Check 2 fails (server starts but ",{"type":46,"tag":116,"props":2593,"children":2595},{"className":2594},[],[2596],{"type":52,"value":2522},{"type":52,"value":2524},{"type":46,"tag":116,"props":2599,"children":2601},{"className":2600},[],[2602],{"type":52,"value":2530},{"type":52,"value":2604}," errors): the server can speak MCP but cannot reach or read Dataverse. Run ",{"type":46,"tag":116,"props":2606,"children":2608},{"className":2607},[],[2609],{"type":52,"value":2610},"--validate",{"type":52,"value":2612}," below to diagnose.",{"type":46,"tag":55,"props":2614,"children":2615},{},[2616],{"type":46,"tag":68,"props":2617,"children":2618},{},[2619,2621,2626],{"type":52,"value":2620},"Diagnostic — ",{"type":46,"tag":116,"props":2622,"children":2624},{"className":2623},[],[2625],{"type":52,"value":2610},{"type":52,"value":2627}," (for failure investigation only):",{"type":46,"tag":640,"props":2629,"children":2632},{"className":2630,"code":2631,"language":52},[643],"npx @microsoft\u002Fdataverse mcp {DATAVERSE_URL} --validate\n",[2633],{"type":46,"tag":116,"props":2634,"children":2635},{"__ignoreMap":648},[2636],{"type":52,"value":2631},{"type":46,"tag":55,"props":2638,"children":2639},{},[2640],{"type":52,"value":2641},"This exercises two Dataverse MCP endpoints with a fresh authentication handshake and reports detailed errors (auth, allowlist, consent, endpoint reachability):",{"type":46,"tag":832,"props":2643,"children":2644},{},[2645,2662],{"type":46,"tag":149,"props":2646,"children":2647},{},[2648,2653,2654,2660],{"type":46,"tag":68,"props":2649,"children":2650},{},[2651],{"type":52,"value":2652},"GA \u002F Production endpoint",{"type":52,"value":195},{"type":46,"tag":116,"props":2655,"children":2657},{"className":2656},[],[2658],{"type":52,"value":2659},"{DATAVERSE_URL}\u002Fapi\u002Fmcp",{"type":52,"value":2661},". This is the one the plugin actually uses at runtime.",{"type":46,"tag":149,"props":2663,"children":2664},{},[2665,2670,2671,2677],{"type":46,"tag":68,"props":2666,"children":2667},{},[2668],{"type":52,"value":2669},"Preview endpoint",{"type":52,"value":195},{"type":46,"tag":116,"props":2672,"children":2674},{"className":2673},[],[2675],{"type":52,"value":2676},"{DATAVERSE_URL}\u002Fapi\u002Fmcp_preview",{"type":52,"value":2678},". Opt-in per environment; not used by the plugin.",{"type":46,"tag":55,"props":2680,"children":2681},{},[2682,2694,2696,2701,2703,2709,2710,2716,2718,2723],{"type":46,"tag":68,"props":2683,"children":2684},{},[2685,2687,2692],{"type":52,"value":2686},"Do not use ",{"type":46,"tag":116,"props":2688,"children":2690},{"className":2689},[],[2691],{"type":52,"value":2610},{"type":52,"value":2693}," as a success gate on first-time setup.",{"type":52,"value":2695}," On a freshly configured workspace, the token cache hasn't warmed up, so ",{"type":46,"tag":116,"props":2697,"children":2699},{"className":2698},[],[2700],{"type":52,"value":2610},{"type":52,"value":2702}," can fail with ",{"type":46,"tag":116,"props":2704,"children":2706},{"className":2705},[],[2707],{"type":52,"value":2708},"MsalClientException",{"type":52,"value":2040},{"type":46,"tag":116,"props":2711,"children":2713},{"className":2712},[],[2714],{"type":52,"value":2715},"403",{"type":52,"value":2717}," while MCP is actually working fine on subsequent real calls. Reserve ",{"type":46,"tag":116,"props":2719,"children":2721},{"className":2720},[],[2722],{"type":52,"value":2610},{"type":52,"value":2724}," for diagnosing a confirmed failure in Check 1 or Check 2.",{"type":46,"tag":55,"props":2726,"children":2727},{},[2728],{"type":46,"tag":68,"props":2729,"children":2730},{},[2731,2733,2738],{"type":52,"value":2732},"How to read ",{"type":46,"tag":116,"props":2734,"children":2736},{"className":2735},[],[2737],{"type":52,"value":2610},{"type":52,"value":2739}," output:",{"type":46,"tag":832,"props":2741,"children":2742},{},[2743,2760,2786,2839],{"type":46,"tag":149,"props":2744,"children":2745},{},[2746,2758],{"type":46,"tag":68,"props":2747,"children":2748},{},[2749,2751,2756],{"type":52,"value":2750},"Look at the GA \u002F Production endpoint (",{"type":46,"tag":116,"props":2752,"children":2754},{"className":2753},[],[2755],{"type":52,"value":2131},{"type":52,"value":2757},") result first.",{"type":52,"value":2759}," If this passes, MCP will work for normal plugin usage regardless of what the Preview endpoint reports.",{"type":46,"tag":149,"props":2761,"children":2762},{},[2763,2784],{"type":46,"tag":68,"props":2764,"children":2765},{},[2766,2768,2774,2776,2782],{"type":52,"value":2767},"A ",{"type":46,"tag":116,"props":2769,"children":2771},{"className":2770},[],[2772],{"type":52,"value":2773},"403 Forbidden",{"type":52,"value":2775}," on the Preview endpoint (",{"type":46,"tag":116,"props":2777,"children":2779},{"className":2778},[],[2780],{"type":52,"value":2781},"\u002Fapi\u002Fmcp_preview",{"type":52,"value":2783},") is expected for most environments.",{"type":52,"value":2785}," Preview is opt-in per environment; if your environment hasn't enabled it, the Preview check will always fail. This does not indicate a broken setup.",{"type":46,"tag":149,"props":2787,"children":2788},{},[2789,2802,2804,2810,2812,2817,2818,2823,2825,2830,2832,2837],{"type":46,"tag":68,"props":2790,"children":2791},{},[2792,2794,2800],{"type":52,"value":2793},"Ignore the overall exit code and the ",{"type":46,"tag":116,"props":2795,"children":2797},{"className":2796},[],[2798],{"type":52,"value":2799},"⚠ Partial success",{"type":52,"value":2801}," warning in this case.",{"type":52,"value":2803}," The validator returns exit code ",{"type":46,"tag":116,"props":2805,"children":2807},{"className":2806},[],[2808],{"type":52,"value":2809},"1",{"type":52,"value":2811}," (failure) unless BOTH ",{"type":46,"tag":116,"props":2813,"children":2815},{"className":2814},[],[2816],{"type":52,"value":2131},{"type":52,"value":276},{"type":46,"tag":116,"props":2819,"children":2821},{"className":2820},[],[2822],{"type":52,"value":2781},{"type":52,"value":2824}," pass. Because most environments don't enable the Preview endpoint, ",{"type":46,"tag":116,"props":2826,"children":2828},{"className":2827},[],[2829],{"type":52,"value":2610},{"type":52,"value":2831}," will exit ",{"type":46,"tag":116,"props":2833,"children":2835},{"className":2834},[],[2836],{"type":52,"value":2809},{"type":52,"value":2838}," even when MCP is fully functional via the GA endpoint. Focus on per-endpoint results, not the aggregate status.",{"type":46,"tag":149,"props":2840,"children":2841},{},[2842,2854],{"type":46,"tag":68,"props":2843,"children":2844},{},[2845,2847,2852],{"type":52,"value":2846},"If the GA endpoint (",{"type":46,"tag":116,"props":2848,"children":2850},{"className":2849},[],[2851],{"type":52,"value":2131},{"type":52,"value":2853},") fails:",{"type":52,"value":2855}," that's the real signal to investigate — auth, tenant consent, environment allowlist, or endpoint reachability.",{"type":46,"tag":1147,"props":2857,"children":2859},{"id":2858},"mcp-server-capabilities",[2860],{"type":52,"value":2861},"MCP Server Capabilities",{"type":46,"tag":55,"props":2863,"children":2864},{},[2865,2867,2872,2873,2878,2880,2885],{"type":52,"value":2866},"For what MCP can and can't do (data CRUD + batch up to 25, table\u002Fcolumn creation incl. choice\u002Flookup, ",{"type":46,"tag":116,"props":2868,"children":2870},{"className":2869},[],[2871],{"type":52,"value":2530},{"type":52,"value":2524},{"type":46,"tag":116,"props":2874,"children":2876},{"className":2875},[],[2877],{"type":52,"value":2522},{"type":52,"value":2879},", file upload\u002Fdownload) versus the SDK \u002F Web API, see the ",{"type":46,"tag":68,"props":2881,"children":2882},{},[2883],{"type":52,"value":2884},"overview",{"type":52,"value":2886}," skill's Tool Capabilities matrix.",{"type":46,"tag":55,"props":2888,"children":2889},{},[2890],{"type":52,"value":2891},"After verifying MCP works, tell the user:",{"type":46,"tag":61,"props":2893,"children":2894},{},[2895,2907,2912,2962],{"type":46,"tag":55,"props":2896,"children":2897},{},[2898,2900,2905],{"type":52,"value":2899},"✅ Connected to Dataverse at ",{"type":46,"tag":116,"props":2901,"children":2903},{"className":2902},[],[2904],{"type":52,"value":340},{"type":52,"value":2906},". Tools installed, authenticated, MCP live.",{"type":46,"tag":55,"props":2908,"children":2909},{},[2910],{"type":52,"value":2911},"You can now:",{"type":46,"tag":832,"props":2913,"children":2914},{},[2915,2927,2939,2951],{"type":46,"tag":149,"props":2916,"children":2917},{},[2918,2920,2926],{"type":52,"value":2919},"Create tables, columns, and relationships (",{"type":46,"tag":116,"props":2921,"children":2923},{"className":2922},[],[2924],{"type":52,"value":2925},"dv-metadata",{"type":52,"value":2133},{"type":46,"tag":149,"props":2928,"children":2929},{},[2930,2932,2938],{"type":52,"value":2931},"Write and import data (",{"type":46,"tag":116,"props":2933,"children":2935},{"className":2934},[],[2936],{"type":52,"value":2937},"dv-data",{"type":52,"value":2133},{"type":46,"tag":149,"props":2940,"children":2941},{},[2942,2944,2950],{"type":52,"value":2943},"Query and analyze data (",{"type":46,"tag":116,"props":2945,"children":2947},{"className":2946},[],[2948],{"type":52,"value":2949},"dv-query",{"type":52,"value":2133},{"type":46,"tag":149,"props":2952,"children":2953},{},[2954,2956,2961],{"type":52,"value":2955},"Export and promote solutions (",{"type":46,"tag":116,"props":2957,"children":2959},{"className":2958},[],[2960],{"type":52,"value":274},{"type":52,"value":2133},{"type":46,"tag":55,"props":2963,"children":2964},{},[2965,2967,2972],{"type":52,"value":2966},"To create your first solution, see the ",{"type":46,"tag":116,"props":2968,"children":2970},{"className":2969},[],[2971],{"type":52,"value":274},{"type":52,"value":2973}," skill.\nTo load sample data (accounts, contacts, opportunities), ask: \"Load demo data into my Dataverse environment.\"",{"type":46,"tag":100,"props":2975,"children":2976},{},[],{"type":46,"tag":104,"props":2978,"children":2980},{"id":2979},"supported-agents",[2981],{"type":52,"value":2982},"Supported Agents",{"type":46,"tag":55,"props":2984,"children":2985},{},[2986,2988,2993,2994,2999],{"type":52,"value":2987},"This plugin's skill files are natively loaded by both ",{"type":46,"tag":68,"props":2989,"children":2990},{},[2991],{"type":52,"value":2992},"GitHub Copilot CLI",{"type":52,"value":276},{"type":46,"tag":68,"props":2995,"children":2996},{},[2997],{"type":52,"value":2998},"Claude Code CLI",{"type":52,"value":3000}," when installed as a plugin. No manual context-loading is needed — both agents discover and invoke skills automatically.",{"type":46,"tag":55,"props":3002,"children":3003},{},[3004],{"type":52,"value":3005},"The PAC CLI commands, Python scripts, and XML templates work identically in both environments.",{"type":46,"tag":3007,"props":3008,"children":3009},"style",{},[3010],{"type":52,"value":3011},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":3013,"total":3205},[3014,3036,3057,3078,3093,3109,3120,3133,3148,3161,3180,3193],{"slug":3015,"name":3015,"fn":3016,"description":3017,"org":3018,"tags":3019,"stars":3033,"repoUrl":3034,"updatedAt":3035},"rushstack-best-practices","manage Rush monorepos with best practices","Provides best practices and guidance for working with Rush monorepos. Use when the user is working in a Rush-based repository, asks about Rush commands (install, update, build, rebuild), needs help with project selection, dependency management, build caching, subspace configuration, or troubleshooting Rush-specific issues.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3020,3023,3026,3027,3030],{"name":3021,"slug":3022,"type":15},"Engineering","engineering",{"name":3024,"slug":3025,"type":15},"Local Development","local-development",{"name":9,"slug":8,"type":15},{"name":3028,"slug":3029,"type":15},"Project Management","project-management",{"name":3031,"slug":3032,"type":15},"Rush","rush",6484,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Frushstack","2026-04-06T18:34:44.965032",{"slug":3037,"name":3037,"fn":3038,"description":3039,"org":3040,"tags":3041,"stars":3054,"repoUrl":3055,"updatedAt":3056},"azure-ai-agents-persistent-dotnet","build AI agents with Azure .NET SDK","Azure AI Agents Persistent SDK for .NET. Low-level SDK for creating and managing AI agents with threads, messages, runs, and tools. Use for agent CRUD, conversation threads, streaming responses, function calling, file search, and code interpreter. Triggers: \"PersistentAgentsClient\", \"persistent agents\", \"agent threads\", \"agent runs\", \"streaming agents\", \"function calling agents .NET\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3042,3045,3048,3051],{"name":3043,"slug":3044,"type":15},".NET","net",{"name":3046,"slug":3047,"type":15},"Agents","agents",{"name":3049,"slug":3050,"type":15},"Azure","azure",{"name":3052,"slug":3053,"type":15},"LLM","llm",2804,"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Fskills","2026-07-03T16:32:10.297433",{"slug":3058,"name":3058,"fn":3059,"description":3060,"org":3061,"tags":3062,"stars":3054,"repoUrl":3055,"updatedAt":3077},"azure-ai-anomalydetector-java","build anomaly detection applications with Java","Build anomaly detection applications with Azure AI Anomaly Detector SDK for Java. Use when implementing univariate\u002Fmultivariate anomaly detection, time-series analysis, or AI-powered monitoring.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3063,3066,3067,3070,3073,3074],{"name":3064,"slug":3065,"type":15},"Analytics","analytics",{"name":3049,"slug":3050,"type":15},{"name":3068,"slug":3069,"type":15},"Data Analysis","data-analysis",{"name":3071,"slug":3072,"type":15},"Java","java",{"name":9,"slug":8,"type":15},{"name":3075,"slug":3076,"type":15},"Monitoring","monitoring","2026-05-13T06:14:16.261754",{"slug":3079,"name":3079,"fn":3080,"description":3081,"org":3082,"tags":3083,"stars":3054,"repoUrl":3055,"updatedAt":3092},"azure-ai-contentsafety-java","build content moderation applications with Azure AI","Build content moderation applications with Azure AI Content Safety SDK for Java. Use when implementing text\u002Fimage analysis, blocklist management, or harm detection for hate, violence, sexual content, and self-harm.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3084,3087,3088,3089],{"name":3085,"slug":3086,"type":15},"AI Infrastructure","ai-infrastructure",{"name":3049,"slug":3050,"type":15},{"name":3071,"slug":3072,"type":15},{"name":3090,"slug":3091,"type":15},"Security","security","2026-07-07T06:53:31.293235",{"slug":3094,"name":3094,"fn":3095,"description":3096,"org":3097,"tags":3098,"stars":3054,"repoUrl":3055,"updatedAt":3108},"azure-ai-contentsafety-py","detect harmful content with Azure AI Content Safety","Azure AI Content Safety SDK for Python. Use for detecting harmful content in text and images with multi-severity classification.\nTriggers: \"azure-ai-contentsafety\", \"ContentSafetyClient\", \"content moderation\", \"harmful content\", \"text analysis\", \"image analysis\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3099,3100,3103,3104,3105,3107],{"name":3049,"slug":3050,"type":15},{"name":3101,"slug":3102,"type":15},"Compliance","compliance",{"name":3052,"slug":3053,"type":15},{"name":9,"slug":8,"type":15},{"name":3106,"slug":1423,"type":15},"Python",{"name":3090,"slug":3091,"type":15},"2026-07-18T05:14:23.017504",{"slug":3110,"name":3110,"fn":3111,"description":3112,"org":3113,"tags":3114,"stars":3054,"repoUrl":3055,"updatedAt":3119},"azure-ai-language-conversations-py","implement conversational language understanding with Python","Implement Conversational Language Understanding (CLU) using the azure-ai-language-conversations Python SDK. Use when working with ConversationAnalysisClient to analyze conversation intent and entities, building NLP features, or integrating language understanding into applications.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3115,3116,3117,3118],{"name":3064,"slug":3065,"type":15},{"name":3049,"slug":3050,"type":15},{"name":3052,"slug":3053,"type":15},{"name":3106,"slug":1423,"type":15},"2026-07-31T05:54:29.068751",{"slug":3121,"name":3121,"fn":3122,"description":3123,"org":3124,"tags":3125,"stars":3054,"repoUrl":3055,"updatedAt":3132},"azure-ai-translation-text-py","translate text using Azure AI services","Azure AI Text Translation SDK for real-time text translation, transliteration, language detection, and dictionary lookup. Use for translating text content in applications.\nTriggers: \"text translation\", \"translator\", \"translate text\", \"transliterate\", \"TextTranslationClient\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3126,3129,3130,3131],{"name":3127,"slug":3128,"type":15},"API Development","api-development",{"name":3049,"slug":3050,"type":15},{"name":9,"slug":8,"type":15},{"name":3106,"slug":1423,"type":15},"2026-07-18T05:14:16.988376",{"slug":3134,"name":3134,"fn":3135,"description":3136,"org":3137,"tags":3138,"stars":3054,"repoUrl":3055,"updatedAt":3147},"azure-ai-vision-imageanalysis-py","analyze images with Azure AI Vision","Azure AI Vision Image Analysis SDK for captions, tags, objects, OCR, people detection, and smart cropping. Use for computer vision and image understanding tasks.\nTriggers: \"image analysis\", \"computer vision\", \"OCR\", \"object detection\", \"ImageAnalysisClient\", \"image caption\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3139,3140,3143,3146],{"name":3049,"slug":3050,"type":15},{"name":3141,"slug":3142,"type":15},"Computer Vision","computer-vision",{"name":3144,"slug":3145,"type":15},"Images","images",{"name":3106,"slug":1423,"type":15},"2026-07-18T05:14:18.007737",{"slug":3149,"name":3149,"fn":3150,"description":3151,"org":3152,"tags":3153,"stars":3054,"repoUrl":3055,"updatedAt":3160},"azure-appconfiguration-java","manage configuration with Azure App Configuration","Azure App Configuration SDK for Java. Centralized application configuration management with key-value settings, feature flags, and snapshots.\nTriggers: \"ConfigurationClient java\", \"app configuration java\", \"feature flag java\", \"configuration setting java\", \"azure config java\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3154,3155,3156,3159],{"name":3049,"slug":3050,"type":15},{"name":13,"slug":14,"type":15},{"name":3157,"slug":3158,"type":15},"Feature Flags","feature-flags",{"name":3071,"slug":3072,"type":15},"2026-07-03T16:32:01.278468",{"slug":3162,"name":3162,"fn":3163,"description":3164,"org":3165,"tags":3166,"stars":3054,"repoUrl":3055,"updatedAt":3179},"azure-cosmos-rust","build applications with Azure Cosmos DB","Azure Cosmos DB library for Rust (NoSQL API). Document CRUD, containers, and globally distributed data.\nTriggers: \"cosmos db rust\", \"CosmosClient rust\", \"document crud rust\", \"NoSQL rust\", \"partition key rust\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3167,3170,3173,3176],{"name":3168,"slug":3169,"type":15},"Cosmos DB","cosmos-db",{"name":3171,"slug":3172,"type":15},"Database","database",{"name":3174,"slug":3175,"type":15},"NoSQL","nosql",{"name":3177,"slug":3178,"type":15},"Rust","rust","2026-07-31T05:54:27.021432",{"slug":3181,"name":3181,"fn":3163,"description":3182,"org":3183,"tags":3184,"stars":3054,"repoUrl":3055,"updatedAt":3192},"azure-cosmos-ts","Azure Cosmos DB JavaScript\u002FTypeScript SDK (@azure\u002Fcosmos) for data plane operations. Use for CRUD operations on documents, queries, bulk operations, and container management. Triggers: \"Cosmos DB\", \"@azure\u002Fcosmos\", \"CosmosClient\", \"document CRUD\", \"NoSQL queries\", \"bulk operations\", \"partition key\", \"container.items\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3185,3186,3187,3188,3189],{"name":3168,"slug":3169,"type":15},{"name":3171,"slug":3172,"type":15},{"name":9,"slug":8,"type":15},{"name":3174,"slug":3175,"type":15},{"name":3190,"slug":3191,"type":15},"TypeScript","typescript","2026-07-03T16:31:19.368382",{"slug":3194,"name":3194,"fn":3195,"description":3196,"org":3197,"tags":3198,"stars":3054,"repoUrl":3055,"updatedAt":3204},"azure-data-tables-java","build table storage applications with Java","Build table storage applications with Azure Tables SDK for Java. Use when working with Azure Table Storage or Cosmos DB Table API for NoSQL key-value data, schemaless storage, or structured data at scale.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3199,3200,3201,3202,3203],{"name":3049,"slug":3050,"type":15},{"name":3168,"slug":3169,"type":15},{"name":3171,"slug":3172,"type":15},{"name":3071,"slug":3072,"type":15},{"name":3174,"slug":3175,"type":15},"2026-05-13T06:14:17.582229",267,{"items":3207,"total":1115},[3208,3215,3229],{"slug":4,"name":4,"fn":5,"description":6,"org":3209,"tags":3210,"stars":23,"repoUrl":24,"updatedAt":25},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3211,3212,3213,3214],{"name":13,"slug":14,"type":15},{"name":21,"slug":22,"type":15},{"name":18,"slug":19,"type":15},{"name":9,"slug":8,"type":15},{"slug":3216,"name":3216,"fn":3217,"description":3218,"org":3219,"tags":3220,"stars":23,"repoUrl":24,"updatedAt":3228},"dv-overview","manage Dataverse and Power Platform environments","Foundational cross-cutting context for Dataverse \u002F Power Platform work — scope and the skill map, the tool-capability reference, the safety rules, and the safe change lifecycle. Use when the user mentions Dataverse, Dynamics 365, Power Platform, CRM, or ERP; load this first for orientation. Specialist skills self-route via their own frontmatter triggers.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3221,3222,3223,3226],{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":3224,"slug":3225,"type":15},"Operations","operations",{"name":3227,"slug":34,"type":15},"Power Platform","2026-07-31T05:54:50.051254",{"slug":3230,"name":3230,"fn":3231,"description":3232,"org":3233,"tags":3234,"stars":23,"repoUrl":24,"updatedAt":3241},"dv-security","manage security and access in Dataverse","Security-role assignment, user access, application users, business units, and admin self-elevation in Dataverse environments. Use when the user wants to give someone access, grant a role, become an admin, or add a service principal.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3235,3238,3239,3240],{"name":3236,"slug":3237,"type":15},"Access Control","access-control",{"name":21,"slug":22,"type":15},{"name":9,"slug":8,"type":15},{"name":3090,"slug":3091,"type":15},"2026-07-24T05:41:15.889984"]