mcp-dataverse 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CAPABILITIES.md +6 -4
- package/README.md +149 -244
- package/assets/logo.webp +0 -0
- package/dist/resources/resource-provider.d.ts +11 -0
- package/dist/resources/resource-provider.d.ts.map +1 -0
- package/dist/resources/resource-provider.js +79 -0
- package/dist/resources/resource-provider.js.map +1 -0
- package/dist/server.js +24 -5
- package/dist/server.js.map +1 -1
- package/dist/tools/actions.tools.js +6 -6
- package/dist/tools/actions.tools.js.map +1 -1
- package/dist/tools/annotations.tools.js +2 -2
- package/dist/tools/annotations.tools.js.map +1 -1
- package/dist/tools/audit.tools.d.ts.map +1 -1
- package/dist/tools/audit.tools.js +4 -1
- package/dist/tools/audit.tools.js.map +1 -1
- package/dist/tools/auth.tools.js +1 -1
- package/dist/tools/auth.tools.js.map +1 -1
- package/dist/tools/batch.tools.d.ts +2 -1
- package/dist/tools/batch.tools.d.ts.map +1 -1
- package/dist/tools/batch.tools.js +4 -2
- package/dist/tools/batch.tools.js.map +1 -1
- package/dist/tools/crud.tools.js +6 -6
- package/dist/tools/crud.tools.js.map +1 -1
- package/dist/tools/customization.tools.js +3 -3
- package/dist/tools/customization.tools.js.map +1 -1
- package/dist/tools/environment.tools.js +2 -2
- package/dist/tools/environment.tools.js.map +1 -1
- package/dist/tools/file.tools.js +2 -2
- package/dist/tools/file.tools.js.map +1 -1
- package/dist/tools/guardrails.d.ts +22 -0
- package/dist/tools/guardrails.d.ts.map +1 -0
- package/dist/tools/guardrails.js +55 -0
- package/dist/tools/guardrails.js.map +1 -0
- package/dist/tools/impersonate.tools.d.ts +2 -1
- package/dist/tools/impersonate.tools.d.ts.map +1 -1
- package/dist/tools/impersonate.tools.js +1 -1
- package/dist/tools/impersonate.tools.js.map +1 -1
- package/dist/tools/metadata.tools.js +7 -7
- package/dist/tools/metadata.tools.js.map +1 -1
- package/dist/tools/org.tools.js +1 -1
- package/dist/tools/org.tools.js.map +1 -1
- package/dist/tools/progress.d.ts +15 -0
- package/dist/tools/progress.d.ts.map +1 -0
- package/dist/tools/progress.js +29 -0
- package/dist/tools/progress.js.map +1 -0
- package/dist/tools/quality.tools.js +1 -1
- package/dist/tools/quality.tools.js.map +1 -1
- package/dist/tools/query.tools.d.ts +2 -1
- package/dist/tools/query.tools.d.ts.map +1 -1
- package/dist/tools/query.tools.js +6 -4
- package/dist/tools/query.tools.js.map +1 -1
- package/dist/tools/relations.tools.js +2 -2
- package/dist/tools/relations.tools.js.map +1 -1
- package/dist/tools/router.tools.d.ts +5 -0
- package/dist/tools/router.tools.d.ts.map +1 -0
- package/dist/tools/router.tools.js +247 -0
- package/dist/tools/router.tools.js.map +1 -0
- package/dist/tools/search.tools.js +1 -1
- package/dist/tools/search.tools.js.map +1 -1
- package/dist/tools/solution.tools.js +3 -3
- package/dist/tools/solution.tools.js.map +1 -1
- package/dist/tools/teams.tools.d.ts.map +1 -1
- package/dist/tools/teams.tools.js +4 -1
- package/dist/tools/teams.tools.js.map +1 -1
- package/dist/tools/tool-registry.d.ts +2 -1
- package/dist/tools/tool-registry.d.ts.map +1 -1
- package/dist/tools/tool-registry.js.map +1 -1
- package/dist/tools/trace.tools.js +2 -2
- package/dist/tools/trace.tools.js.map +1 -1
- package/dist/tools/tracking.tools.js +1 -1
- package/dist/tools/tracking.tools.js.map +1 -1
- package/dist/tools/users.tools.js +2 -2
- package/dist/tools/users.tools.js.map +1 -1
- package/dist/tools/views.tools.js +1 -1
- package/dist/tools/views.tools.js.map +1 -1
- package/dist/tools/workflow.tools.d.ts +53 -0
- package/dist/tools/workflow.tools.d.ts.map +1 -0
- package/dist/tools/workflow.tools.js +198 -0
- package/dist/tools/workflow.tools.js.map +1 -0
- package/package.json +3 -2
- package/server.json +3 -3
package/CAPABILITIES.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# MCP Dataverse Server — Complete Capabilities Reference
|
|
2
2
|
|
|
3
|
-
> **Version**: 0.
|
|
3
|
+
> **Version**: 0.3.1 | **API Version**: Dataverse Web API v9.2 | **Transport**: stdio · HTTP/SSE
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
54 tools across 23 categories for full Dataverse lifecycle: schema, CRUD, FetchXML, solutions, plugins, audit, files, users, teams, environment variables, and more.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -91,12 +91,12 @@ Server communicates over **stdio** (MCP SDK `StdioServerTransport`). Connect fro
|
|
|
91
91
|
|
|
92
92
|
```mermaid
|
|
93
93
|
graph LR
|
|
94
|
-
MCP["MCP Dataverse Server<br/><i>
|
|
94
|
+
MCP["MCP Dataverse Server<br/><i>54 tools · 23 categories</i>"]
|
|
95
95
|
|
|
96
96
|
MCP --> AUTH["🔑 Auth (1)"]
|
|
97
97
|
MCP --> META["📋 Metadata (8)"]
|
|
98
98
|
MCP --> QUERY["🔍 Query (3)"]
|
|
99
|
-
MCP --> CRUD["✏️ CRUD (
|
|
99
|
+
MCP --> CRUD["✏️ CRUD (6)"]
|
|
100
100
|
MCP --> REL["🔗 Relations (2)"]
|
|
101
101
|
MCP --> ACT["⚡ Actions & Functions (6)"]
|
|
102
102
|
MCP --> BATCH["📦 Batch (1)"]
|
|
@@ -114,6 +114,8 @@ graph LR
|
|
|
114
114
|
MCP --> VIEWS["👁️ Views (1)"]
|
|
115
115
|
MCP --> FILES["📁 Files (2)"]
|
|
116
116
|
MCP --> ORG["🏢 Org (1)"]
|
|
117
|
+
MCP --> TEAMS["👥 Teams (1)"]
|
|
118
|
+
MCP --> ASSIST["🤖 Assistance (4)"]
|
|
117
119
|
```
|
|
118
120
|
|
|
119
121
|
All tool handlers validate inputs with **Zod** before calling the `DataverseAdvancedClient`. Auth tokens are cached and refreshed proactively; transient errors (429, 503, 504) are retried with exponential backoff.
|
package/README.md
CHANGED
|
@@ -1,59 +1,53 @@
|
|
|
1
|
-
# MCP Dataverse
|
|
1
|
+
# MCP Dataverse
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<div align="center">
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<img src="assets/logo.webp" alt="MCP Dataverse" width="180" />
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
**The most complete MCP server for Microsoft Dataverse.**
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
54 tools · 4 resources · 10 guided workflows · Zero config auth
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
[](https://www.npmjs.com/package/mcp-dataverse)
|
|
12
|
+
[](https://www.npmjs.com/package/mcp-dataverse)
|
|
13
|
+
[](https://github.com/codeurali/mcp-dataverse/actions/workflows/ci.yml)
|
|
14
|
+
[](https://nodejs.org)
|
|
15
|
+
[](https://www.typescriptlang.org)
|
|
16
|
+
[](LICENSE)
|
|
12
17
|
|
|
13
|
-
|
|
14
|
-
npx mcp-dataverse install
|
|
15
|
-
```
|
|
18
|
+
[Install](#install) · [Capabilities](#capabilities) · [Tools](#tools-54) · [Multi-Client Setup](docs/multi-client-setup.md) · [Full Reference](CAPABILITIES.md)
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
</div>
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
2. Save configuration to `~/.mcp-dataverse/config.json`
|
|
21
|
-
3. Register the server in VS Code and/or VS Code Insiders via `code --add-mcp`
|
|
22
|
-
4. Authenticate with your Microsoft account (device code flow)
|
|
22
|
+
---
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
## Why MCP Dataverse?
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
AI agents hallucinate schema, guess column names, and build broken OData queries. This server gives them **real-time access** to your Dataverse environment — schema, records, metadata, solutions — through the Model Context Protocol.
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
- **No Azure AD app registration** — device code flow, zero pre-configuration
|
|
29
|
+
- **Works with any MCP client** — VS Code, Claude, Cursor, Windsurf, Gemini, Codex CLI
|
|
30
|
+
- **Atomic tools** — each tool does one thing well; the AI picks the right one
|
|
31
|
+
- **Structured outputs** — every response returns `{summary, data, suggestions}`
|
|
32
|
+
- **Guardrails** — destructive operations require explicit confirmation
|
|
33
|
+
- **Encrypted tokens** — AES-256-GCM cached credentials, never logged
|
|
29
34
|
|
|
30
|
-
|
|
35
|
+
---
|
|
31
36
|
|
|
32
|
-
|
|
33
|
-
2. Type **`MCP: Add Server`** → choose **`NPM Package`** → enter **`mcp-dataverse`**
|
|
34
|
-
3. Choose the scope: **User** or **Workspace**
|
|
35
|
-
4. Edit the generated entry to add your environment URL:
|
|
37
|
+
## Install
|
|
36
38
|
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
"servers": {
|
|
40
|
-
"mcp-dataverse": {
|
|
41
|
-
"type": "stdio",
|
|
42
|
-
"command": "npx",
|
|
43
|
-
"args": ["-y", "mcp-dataverse"],
|
|
44
|
-
"env": {
|
|
45
|
-
"MCP_CONFIG_PATH": "/path/to/.mcp-dataverse/config.json"
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
39
|
+
```bash
|
|
40
|
+
npx mcp-dataverse install
|
|
50
41
|
```
|
|
51
42
|
|
|
52
|
-
|
|
43
|
+
The interactive wizard configures your environment, registers the server in VS Code, and authenticates your Microsoft account. Done in under 2 minutes.
|
|
53
44
|
|
|
54
|
-
|
|
45
|
+
> Requires Node.js 20+ and VS Code 1.99+. For other clients (Claude, Cursor, Windsurf…), see [Multi-Client Setup](docs/multi-client-setup.md).
|
|
55
46
|
|
|
56
|
-
|
|
47
|
+
<details>
|
|
48
|
+
<summary><strong>Manual setup (mcp.json)</strong></summary>
|
|
49
|
+
|
|
50
|
+
Add to `.vscode/mcp.json` or user-level MCP configuration:
|
|
57
51
|
|
|
58
52
|
```jsonc
|
|
59
53
|
{
|
|
@@ -70,258 +64,169 @@ Create or edit `.vscode/mcp.json` (workspace scope) or the user-level `mcp.json`
|
|
|
70
64
|
}
|
|
71
65
|
```
|
|
72
66
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
## Authentication — automatic, no setup required
|
|
76
|
-
|
|
77
|
-
**No PAC CLI, no Azure AD app registration, no credentials to configure.**
|
|
78
|
-
|
|
79
|
-
The server uses Microsoft's device code flow (MSAL Public Client) — the same mechanism used by Power Platform CLI. Zero pre-configuration: just set your environment URL and the server handles the rest.
|
|
80
|
-
|
|
81
|
-
### First connection — what you'll see
|
|
82
|
-
|
|
83
|
-
Authentication is triggered on the **first tool call** after the server starts (e.g. asking Copilot _"Who am I in Dataverse?"_). Here is the exact sequence:
|
|
84
|
-
|
|
85
|
-
**Step 1 — Open the Output panel**
|
|
86
|
-
|
|
87
|
-
In VS Code: **View → Output** → select **MCP** in the dropdown.
|
|
88
|
-
|
|
89
|
-
**Step 2 — The sign-in prompt appears**
|
|
90
|
-
|
|
91
|
-
```
|
|
92
|
-
[mcp-dataverse] First-time authentication required.
|
|
93
|
-
Environment: https://yourorg.crm.dynamics.com
|
|
94
|
-
Open the URL below in your browser to sign in.
|
|
95
|
-
|
|
96
|
-
[mcp-dataverse] Sign in required
|
|
97
|
-
|
|
98
|
-
1. Open https://microsoft.com/devicelogin in your browser
|
|
99
|
-
(use the browser profile linked to your Power Platform account)
|
|
100
|
-
2. Paste the code: ABCD-1234 (already copied to your clipboard)
|
|
101
|
-
3. Sign in with your work account
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
**Step 3 — Sign in**
|
|
105
|
-
|
|
106
|
-
1. Open `https://microsoft.com/devicelogin` in the browser/profile linked to your **Power Platform work account**
|
|
107
|
-
2. Paste the code — it's already in your clipboard
|
|
108
|
-
3. Complete Microsoft sign-in with your work account
|
|
109
|
-
|
|
110
|
-
**Step 4 — Confirmation in the Output panel**
|
|
111
|
-
|
|
112
|
-
```
|
|
113
|
-
[mcp-dataverse] Authenticated ✓ Token cached — no sign-in needed next time.
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
The tool call that triggered auth now completes. All 50 tools are ready to use.
|
|
117
|
-
|
|
118
|
-
> ⏱ The code expires after **5 minutes**. If it times out, retry the tool call — a new code will be generated.
|
|
67
|
+
</details>
|
|
119
68
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
### Subsequent launches
|
|
123
|
-
|
|
124
|
-
The token is cached encrypted (AES-256-GCM) in `~/.mcp-dataverse/`. On all future server starts, renewal is **completely silent** — no prompt, no browser.
|
|
125
|
-
|
|
126
|
-
You only need to re-authenticate if the refresh token expires (~90 days of inactivity) or you reset it manually:
|
|
127
|
-
|
|
128
|
-
```bash
|
|
129
|
-
npx mcp-dataverse-auth https://yourorg.crm.dynamics.com
|
|
130
|
-
```
|
|
69
|
+
---
|
|
131
70
|
|
|
132
|
-
|
|
71
|
+
## Authentication
|
|
133
72
|
|
|
134
|
-
|
|
135
|
-
[mcp-dataverse] Session expired — re-authenticating.
|
|
136
|
-
Open the URL below in your browser to sign in again.
|
|
73
|
+
**No PAC CLI, no app registration, no client secret.** The server uses Microsoft's device code flow (MSAL Public Client).
|
|
137
74
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
75
|
+
1. **First tool call** → a sign-in code appears in the Output panel (`View → Output → MCP`)
|
|
76
|
+
2. Open `https://microsoft.com/devicelogin` → paste the code → sign in with your work account
|
|
77
|
+
3. **Done.** Token is cached encrypted — all future starts are silent
|
|
141
78
|
|
|
142
|
-
|
|
79
|
+
Re-authentication is only needed after ~90 days of inactivity: `npx mcp-dataverse-auth`
|
|
143
80
|
|
|
144
81
|
---
|
|
145
82
|
|
|
146
|
-
##
|
|
83
|
+
## Capabilities
|
|
147
84
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
85
|
+
| Capability | Description |
|
|
86
|
+
|---|---|
|
|
87
|
+
| **54 Tools** | Full Dataverse lifecycle — schema, CRUD, query, FetchXML, batch, search, audit, files, solutions, and more |
|
|
88
|
+
| **4 Resources** | `dataverse://tables`, schema templates, relationship templates, server instructions |
|
|
89
|
+
| **10 Workflows** | Guided multi-step sequences for common tasks (explore schema, create record, bulk operations…) |
|
|
90
|
+
| **Tool Router** | Intent-based tool suggestion — ask what you need, get the right tools |
|
|
91
|
+
| **Progress Notifications** | Real-time progress for paging and batch operations |
|
|
92
|
+
| **HTTP + SSE Transport** | Supports both stdio (default) and HTTP/SSE (`--transport http --port 3001`) |
|
|
151
93
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
### 1. Clone & install
|
|
155
|
-
|
|
156
|
-
```bash
|
|
157
|
-
git clone <repo-url> mcp-dataverse && cd mcp-dataverse
|
|
158
|
-
npm install
|
|
159
|
-
```
|
|
94
|
+
---
|
|
160
95
|
|
|
161
|
-
|
|
96
|
+
## Tools (54)
|
|
97
|
+
|
|
98
|
+
### Core (50 tools)
|
|
99
|
+
|
|
100
|
+
| Category | Count | Tools |
|
|
101
|
+
|----------|-------|-------|
|
|
102
|
+
| **Metadata** | 8 | List tables, get schema, relationships, option sets, entity keys |
|
|
103
|
+
| **Query** | 3 | OData query, FetchXML, paginated retrieval |
|
|
104
|
+
| **CRUD** | 6 | Get, create, update, delete, upsert, assign |
|
|
105
|
+
| **Relations** | 2 | Associate, disassociate |
|
|
106
|
+
| **Actions & Functions** | 6 | Execute bound/unbound actions and functions, dependency checks |
|
|
107
|
+
| **Batch** | 1 | Up to 1000 operations in a single atomic request |
|
|
108
|
+
| **Solutions** | 3 | List solutions, components, publish customizations |
|
|
109
|
+
| **Customization** | 3 | Custom actions, plugin steps, workflow state |
|
|
110
|
+
| **Search** | 1 | Dataverse Relevance Search (full-text) |
|
|
111
|
+
| **Audit** | 1 | Record change history |
|
|
112
|
+
| **Trace** | 2 | Plugin trace logs, workflow execution logs |
|
|
113
|
+
| **Environment** | 2 | Get/set environment variables |
|
|
114
|
+
| **Users & Teams** | 3 | List users, roles, teams |
|
|
115
|
+
| **Files** | 2 | Upload/download file and image columns |
|
|
116
|
+
| **Annotations** | 2 | Notes and attachments (read + create) |
|
|
117
|
+
| **Views** | 1 | System and personal saved views |
|
|
118
|
+
| **Org** | 1 | Business units hierarchy |
|
|
119
|
+
| **Tracking** | 1 | Delta change detection with tokens |
|
|
120
|
+
| **Impersonation** | 1 | Execute any tool on behalf of another user |
|
|
121
|
+
| **Quality** | 1 | Duplicate detection |
|
|
122
|
+
| **Auth** | 1 | WhoAmI connection verification |
|
|
123
|
+
|
|
124
|
+
### Assistance (4 tools)
|
|
125
|
+
|
|
126
|
+
| Tool | Purpose |
|
|
127
|
+
|------|---------|
|
|
128
|
+
| `dataverse_suggest_tools` | Describe your intent → get the right tools with usage examples |
|
|
129
|
+
| `dataverse_list_tool_tags` | Browse all tools by category tag |
|
|
130
|
+
| `dataverse_list_workflows` | List available guided workflows |
|
|
131
|
+
| `dataverse_get_workflow` | Get step-by-step instructions for a specific workflow |
|
|
132
|
+
|
|
133
|
+
> Full schema and parameter details → [CAPABILITIES.md](CAPABILITIES.md)
|
|
162
134
|
|
|
163
|
-
|
|
164
|
-
cp config.example.json config.json
|
|
165
|
-
```
|
|
135
|
+
---
|
|
166
136
|
|
|
167
|
-
|
|
137
|
+
## Architecture
|
|
168
138
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
| `requestTimeoutMs` | HTTP timeout in ms (default: `30000`) |
|
|
173
|
-
| `maxRetries` | Retry count on transient errors (default: `3`) |
|
|
139
|
+
```mermaid
|
|
140
|
+
flowchart LR
|
|
141
|
+
CLIENT["MCP Client\nCopilot · Claude · Cursor · Windsurf…"]
|
|
174
142
|
|
|
175
|
-
|
|
143
|
+
CLIENT -->|stdio / HTTP+SSE| SERVER
|
|
176
144
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
145
|
+
subgraph SERVER["MCP Server"]
|
|
146
|
+
direction TB
|
|
147
|
+
REGISTRY["Tool Registry — O(1) dispatch"]
|
|
148
|
+
TOOLS["54 Tools · 4 Resources"]
|
|
149
|
+
GUARD["Guardrails · Annotations · Structured Outputs"]
|
|
150
|
+
end
|
|
180
151
|
|
|
181
|
-
|
|
152
|
+
SERVER --> HTTP
|
|
182
153
|
|
|
183
|
-
|
|
154
|
+
subgraph HTTP["HTTP Layer"]
|
|
155
|
+
direction TB
|
|
156
|
+
HTTPC["HttpClient — native fetch · retry · timeout"]
|
|
157
|
+
AUTH["AuthProvider — MSAL device code flow"]
|
|
158
|
+
end
|
|
184
159
|
|
|
185
|
-
|
|
186
|
-
npm run build
|
|
160
|
+
HTTP --> API["Dataverse\nWeb API v9.2"]
|
|
187
161
|
```
|
|
188
162
|
|
|
189
|
-
|
|
163
|
+
**Stack**: TypeScript strict · Node.js 20+ · Zod validation · 459 tests · GitHub Actions CI
|
|
190
164
|
|
|
191
|
-
|
|
192
|
-
npx tsx tests/live/test-whoami.ts
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
Expected output:
|
|
196
|
-
|
|
197
|
-
```
|
|
198
|
-
WhoAmI result: { UserId: 'xxxxxxxx-...', BusinessUnitId: 'xxxxxxxx-...', OrganizationId: 'xxxxxxxx-...' }
|
|
199
|
-
```
|
|
165
|
+
---
|
|
200
166
|
|
|
201
|
-
|
|
167
|
+
## Configuration
|
|
202
168
|
|
|
203
|
-
|
|
169
|
+
`~/.mcp-dataverse/config.json` (created by the install wizard):
|
|
204
170
|
|
|
205
171
|
```json
|
|
206
172
|
{
|
|
207
|
-
"
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
"command": "node",
|
|
211
|
-
"args": ["${workspaceFolder}/dist/server.js"],
|
|
212
|
-
"env": {}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
173
|
+
"environmentUrl": "https://yourorg.crm.dynamics.com",
|
|
174
|
+
"requestTimeoutMs": 30000,
|
|
175
|
+
"maxRetries": 3
|
|
215
176
|
}
|
|
216
177
|
```
|
|
217
178
|
|
|
218
|
-
|
|
219
|
-
2. Open GitHub Copilot chat → switch to **Agent mode** (⚡)
|
|
220
|
-
3. Test: _"List the Dataverse tables in my environment"_
|
|
179
|
+
Config resolution: `MCP_CONFIG_PATH` env var → `~/.mcp-dataverse/config.json` → `./config.json`
|
|
221
180
|
|
|
222
181
|
---
|
|
223
182
|
|
|
224
|
-
##
|
|
225
|
-
|
|
226
|
-
|
|
|
227
|
-
|
|
228
|
-
| `
|
|
229
|
-
| `
|
|
230
|
-
| `
|
|
231
|
-
| `
|
|
232
|
-
| `dataverse_list_global_option_sets` | Metadata | All global option sets in the environment |
|
|
233
|
-
| `dataverse_get_option_set` | Metadata | Options and values for a specific option set |
|
|
234
|
-
| `dataverse_get_entity_key` | Metadata | Alternate key definitions for a table (fields, index status, customizable flag) |
|
|
235
|
-
| `dataverse_query` | Query | OData query with `$select`, `$filter`, `$orderby`, `$expand`, `$count` |
|
|
236
|
-
| `dataverse_execute_fetchxml` | Query | Raw FetchXML for aggregations and complex joins |
|
|
237
|
-
| `dataverse_retrieve_multiple_with_paging` | Query | Paginated query following `@odata.nextLink`, with configurable `maxTotal` cap |
|
|
238
|
-
| `dataverse_get` | CRUD | Retrieve a single record by GUID |
|
|
239
|
-
| `dataverse_create` | CRUD | Create a record; returns the new GUID |
|
|
240
|
-
| `dataverse_update` | CRUD | Patch a record — only specified fields are changed |
|
|
241
|
-
| `dataverse_delete` | CRUD | Delete a record (requires explicit confirm) |
|
|
242
|
-
| `dataverse_upsert` | CRUD | Create-or-update via alternate key |
|
|
243
|
-
| `dataverse_assign` | CRUD | Assign a record to a different user or team owner |
|
|
244
|
-
| `dataverse_associate` | Relations | Associate two records via a named relationship |
|
|
245
|
-
| `dataverse_disassociate` | Relations | Remove an association between two records |
|
|
246
|
-
| `dataverse_execute_action` | Actions | Execute a global (unbound) Dataverse action |
|
|
247
|
-
| `dataverse_execute_function` | Actions | Execute a global read-only function (e.g. `WhoAmI`) |
|
|
248
|
-
| `dataverse_execute_bound_action` | Actions | Execute an action bound to a specific record |
|
|
249
|
-
| `dataverse_execute_bound_function` | Actions | Execute an OData bound function on a specific record |
|
|
250
|
-
| `dataverse_retrieve_dependencies_for_delete` | Actions | Check what components block deletion of a Dataverse component |
|
|
251
|
-
| `dataverse_list_dependencies` | Actions | List component dependencies before modifying or deleting |
|
|
252
|
-
| `dataverse_batch_execute` | Batch | Up to 1000 operations in a single HTTP batch request; optional atomic changeset |
|
|
253
|
-
| `dataverse_change_detection` | Tracking | Delta tracking using change tokens to detect record changes since last sync |
|
|
254
|
-
| `dataverse_solution_components` | Solution | List all components in a named solution; filter by component type code |
|
|
255
|
-
| `dataverse_publish_customizations` | Solution | Publish pending customizations (all or targeted entities/web resources/option sets) |
|
|
256
|
-
| `dataverse_impersonate` | Impersonation | Execute any tool on behalf of another Dataverse user via `MSCRMCallerId` |
|
|
257
|
-
| `dataverse_list_custom_actions` | Customization | Lists custom actions (custom API / SDK messages) in the environment |
|
|
258
|
-
| `dataverse_list_plugin_steps` | Customization | Lists plugin step registrations with stage, mode, entity, and state |
|
|
259
|
-
| `dataverse_get_environment_variable` | Environment | Retrieve an environment variable definition and current value |
|
|
260
|
-
| `dataverse_set_environment_variable` | Environment | Set or update an environment variable value |
|
|
261
|
-
| `dataverse_get_plugin_trace_logs` | Trace | Retrieve plugin execution trace logs for debugging |
|
|
262
|
-
| `dataverse_get_workflow_trace_logs` | Trace | Retrieve async workflow/system job execution logs |
|
|
263
|
-
| `dataverse_search` | Search | Full-text Relevance Search across all configured tables |
|
|
264
|
-
| `dataverse_get_audit_log` | Audit | Retrieve audit trail for a record showing change history |
|
|
265
|
-
| `dataverse_detect_duplicates` | Quality | Check for potential duplicates before creating a record |
|
|
266
|
-
| `dataverse_get_annotations` | Annotations | Retrieve notes and file attachments linked to a record |
|
|
267
|
-
| `dataverse_list_users` | Users | Search system users by name or email with BU filtering |
|
|
268
|
-
| `dataverse_get_user_roles` | Users | Security roles assigned to a system user |
|
|
269
|
-
| `dataverse_create_annotation` | Annotations | Create a note or file attachment linked to a record |
|
|
270
|
-
| `dataverse_get_attribute_option_set` | Metadata | Local/entity-specific option set values (statecode, statuscode, picklist) |
|
|
271
|
-
| `dataverse_list_solutions` | Solution | List all solutions in the environment |
|
|
272
|
-
| `dataverse_set_workflow_state` | Customization | Enable or disable a workflow or process |
|
|
273
|
-
| `dataverse_list_views` | Views | List system and personal saved views for a table |
|
|
274
|
-
| `dataverse_upload_file_column` | Files | Upload binary content to a file/image column on a record |
|
|
275
|
-
| `dataverse_download_file_column` | Files | Download binary content from a file/image column on a record |
|
|
276
|
-
| `dataverse_list_business_units` | Org | List business units in the environment (org hierarchy) |
|
|
277
|
-
| `dataverse_list_teams` | Teams | List Dataverse teams with optional filter by team type |
|
|
183
|
+
## CLI Commands
|
|
184
|
+
|
|
185
|
+
| Command | Description |
|
|
186
|
+
|---------|-------------|
|
|
187
|
+
| `npx mcp-dataverse install` | Interactive setup wizard |
|
|
188
|
+
| `npx mcp-dataverse doctor` | Diagnose configuration and connectivity issues |
|
|
189
|
+
| `npx mcp-dataverse-auth [url]` | Re-authenticate or switch environment |
|
|
190
|
+
| `npx mcp-dataverse --transport http --port 3001` | Start with HTTP/SSE transport |
|
|
278
191
|
|
|
279
192
|
---
|
|
280
193
|
|
|
281
|
-
##
|
|
194
|
+
## Security
|
|
282
195
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
| `npm run typecheck` | Type-check without emitting output |
|
|
290
|
-
| `npm run lint` | ESLint on `src/` |
|
|
291
|
-
| `npm run test:unit` | Unit tests only |
|
|
292
|
-
| `npm run test:integration` | Integration tests |
|
|
293
|
-
| `npm test` | All tests |
|
|
196
|
+
- **Zero credentials in code** — device code flow, no client secrets
|
|
197
|
+
- **Encrypted token cache** — AES-256-GCM in `~/.mcp-dataverse/`
|
|
198
|
+
- **Tokens never logged** — only diagnostic messages on stderr
|
|
199
|
+
- **Destructive guardrails** — delete operations require explicit `confirm: true`
|
|
200
|
+
- **User-scoped access** — no privilege escalation beyond the authenticated user
|
|
201
|
+
- **Zod validation** — all tool inputs validated at the boundary
|
|
294
202
|
|
|
295
203
|
---
|
|
296
204
|
|
|
297
|
-
##
|
|
298
|
-
|
|
299
|
-
TypeScript MCP server over **stdio** transport. The `DeviceCodeAuthProvider` (MSAL device code flow) injects Bearer tokens into a native-`fetch`-based `HttpClient` wrapped by `DataverseClient`. Each tool module registers handlers with the MCP `Server` instance.
|
|
205
|
+
## Troubleshooting
|
|
300
206
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
207
|
+
| Symptom | Fix |
|
|
208
|
+
|---------|-----|
|
|
209
|
+
| No sign-in prompt | Open **View → Output → MCP** — the device code is displayed there |
|
|
210
|
+
| `No MSAL accounts found` | Run `npx mcp-dataverse-auth` then restart the server |
|
|
211
|
+
| `Authentication timed out` | The 5-minute window expired — restart the MCP server for a new code |
|
|
212
|
+
| Server not appearing in Agent mode | Run `npx mcp-dataverse install` or `npx mcp-dataverse doctor` |
|
|
213
|
+
| HTTP errors | Run `npx mcp-dataverse doctor` to check config, auth, and connectivity |
|
|
305
214
|
|
|
306
215
|
---
|
|
307
216
|
|
|
308
|
-
##
|
|
217
|
+
## Contributing
|
|
309
218
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
219
|
+
```bash
|
|
220
|
+
git clone https://github.com/codeurali/mcp-dataverse.git && cd mcp-dataverse
|
|
221
|
+
npm install
|
|
222
|
+
npm run build
|
|
223
|
+
npm test # 459 tests across 38 suites
|
|
224
|
+
npm run lint # ESLint strict
|
|
225
|
+
npm run typecheck # TypeScript strict mode
|
|
226
|
+
```
|
|
314
227
|
|
|
315
228
|
---
|
|
316
229
|
|
|
317
|
-
##
|
|
230
|
+
## License
|
|
318
231
|
|
|
319
|
-
|
|
320
|
-
| ------------------------------------------ | -------------------------------------------------------------------------------- |
|
|
321
|
-
| No sign-in prompt appeared | Open **View → Output → MCP** in VS Code — the device code is displayed there |
|
|
322
|
-
| Browser didn't open automatically | Copy the URL from the Output panel manually: `https://microsoft.com/devicelogin` |
|
|
323
|
-
| `No MSAL accounts found` | Run `npx mcp-dataverse-auth` to re-authenticate, then restart the server |
|
|
324
|
-
| `Authentication timed out` | The 5-minute window expired — restart the MCP server to get a new code |
|
|
325
|
-
| `"https://" is required` | Check your `~/.mcp-dataverse/config.json` — URL must start with `https://` |
|
|
326
|
-
| Server not appearing in Copilot Agent mode | Re-run `npx mcp-dataverse install`; check **Output → MCP** panel for errors |
|
|
327
|
-
| Install wizard says "not found on PATH" | Install VS Code Shell Command (**Ctrl+Shift+P** → *Shell Command: Install...*) or use the manual snippet provided |
|
|
232
|
+
[MIT](LICENSE) © [codeurali](https://github.com/codeurali)
|
package/assets/logo.webp
ADDED
|
Binary file
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Resource, ResourceTemplate } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import type { DataverseAdvancedClient } from "../dataverse/dataverse-client-advanced.js";
|
|
3
|
+
export interface ResourceContent {
|
|
4
|
+
uri: string;
|
|
5
|
+
mimeType: string;
|
|
6
|
+
text: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function listResources(): Resource[];
|
|
9
|
+
export declare function listResourceTemplates(): ResourceTemplate[];
|
|
10
|
+
export declare function readResource(uri: string, client: DataverseAdvancedClient, serverInstructions: string): Promise<ResourceContent>;
|
|
11
|
+
//# sourceMappingURL=resource-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-provider.d.ts","sourceRoot":"","sources":["../../src/resources/resource-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACrF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AA8EzF,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,aAAa,IAAI,QAAQ,EAAE,CAE1C;AAED,wBAAgB,qBAAqB,IAAI,gBAAgB,EAAE,CAE1D;AAED,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,uBAAuB,EAC/B,kBAAkB,EAAE,MAAM,GACzB,OAAO,CAAC,eAAe,CAAC,CAoB1B"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// ── Resource Templates (dynamic URIs with parameters) ────────────────────────
|
|
2
|
+
const RESOURCE_TEMPLATES = [
|
|
3
|
+
{
|
|
4
|
+
uriTemplate: "dataverse://tables/{tableName}/schema",
|
|
5
|
+
name: "Table Schema",
|
|
6
|
+
description: "Returns the full schema (columns, types, requirements) for a Dataverse table",
|
|
7
|
+
mimeType: "application/json",
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
uriTemplate: "dataverse://tables/{tableName}/relationships",
|
|
11
|
+
name: "Table Relationships",
|
|
12
|
+
description: "Returns all 1:N and N:N relationships for a Dataverse table",
|
|
13
|
+
mimeType: "application/json",
|
|
14
|
+
},
|
|
15
|
+
];
|
|
16
|
+
// ── Static Resources (fixed URIs) ────────────────────────────────────────────
|
|
17
|
+
const STATIC_RESOURCES = [
|
|
18
|
+
{
|
|
19
|
+
uri: "dataverse://tables",
|
|
20
|
+
name: "Available Tables",
|
|
21
|
+
description: "Lists all custom tables in the connected Dataverse environment",
|
|
22
|
+
mimeType: "application/json",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
uri: "dataverse://server/instructions",
|
|
26
|
+
name: "Server Instructions",
|
|
27
|
+
description: "Usage guidelines and best practices for interacting with this Dataverse MCP server",
|
|
28
|
+
mimeType: "text/plain",
|
|
29
|
+
},
|
|
30
|
+
];
|
|
31
|
+
function parseResourceUri(uri) {
|
|
32
|
+
const PREFIX = "dataverse://";
|
|
33
|
+
if (!uri.startsWith(PREFIX)) {
|
|
34
|
+
throw new Error(`Unknown resource URI: ${uri}`);
|
|
35
|
+
}
|
|
36
|
+
const path = uri.slice(PREFIX.length);
|
|
37
|
+
if (path === "tables") {
|
|
38
|
+
return { type: "tables" };
|
|
39
|
+
}
|
|
40
|
+
if (path === "server/instructions") {
|
|
41
|
+
return { type: "instructions" };
|
|
42
|
+
}
|
|
43
|
+
const schemaMatch = /^tables\/([^/]+)\/schema$/.exec(path);
|
|
44
|
+
if (schemaMatch) {
|
|
45
|
+
return { type: "schema", tableName: schemaMatch[1] };
|
|
46
|
+
}
|
|
47
|
+
const relMatch = /^tables\/([^/]+)\/relationships$/.exec(path);
|
|
48
|
+
if (relMatch) {
|
|
49
|
+
return { type: "relationships", tableName: relMatch[1] };
|
|
50
|
+
}
|
|
51
|
+
throw new Error(`Unknown resource URI: ${uri}`);
|
|
52
|
+
}
|
|
53
|
+
export function listResources() {
|
|
54
|
+
return STATIC_RESOURCES;
|
|
55
|
+
}
|
|
56
|
+
export function listResourceTemplates() {
|
|
57
|
+
return RESOURCE_TEMPLATES;
|
|
58
|
+
}
|
|
59
|
+
export async function readResource(uri, client, serverInstructions) {
|
|
60
|
+
const parsed = parseResourceUri(uri);
|
|
61
|
+
switch (parsed.type) {
|
|
62
|
+
case "tables": {
|
|
63
|
+
const tables = await client.listTables(true);
|
|
64
|
+
return { uri, mimeType: "application/json", text: JSON.stringify(tables, null, 2) };
|
|
65
|
+
}
|
|
66
|
+
case "schema": {
|
|
67
|
+
const metadata = await client.getTableMetadata(parsed.tableName);
|
|
68
|
+
return { uri, mimeType: "application/json", text: JSON.stringify(metadata, null, 2) };
|
|
69
|
+
}
|
|
70
|
+
case "relationships": {
|
|
71
|
+
const rels = await client.getRelationships(parsed.tableName);
|
|
72
|
+
return { uri, mimeType: "application/json", text: JSON.stringify(rels, null, 2) };
|
|
73
|
+
}
|
|
74
|
+
case "instructions": {
|
|
75
|
+
return { uri, mimeType: "text/plain", text: serverInstructions };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=resource-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-provider.js","sourceRoot":"","sources":["../../src/resources/resource-provider.ts"],"names":[],"mappings":"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"}
|