@adrata/adrata-mcp 1.0.0

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.
Files changed (41) hide show
  1. package/README.md +548 -0
  2. package/access/auth.js +289 -0
  3. package/access/oauth.js +1059 -0
  4. package/access/resource-metadata.js +167 -0
  5. package/access/tiers.js +422 -0
  6. package/analytics.js +634 -0
  7. package/api-bridge.js +499 -0
  8. package/governance/money.js +141 -0
  9. package/output-formatter.js +589 -0
  10. package/package.json +68 -0
  11. package/resources.js +246 -0
  12. package/security.js +690 -0
  13. package/server.js +2139 -0
  14. package/server.json +55 -0
  15. package/skills/backlog-triage/SKILL.md +115 -0
  16. package/skills/board-review/SKILL.md +96 -0
  17. package/skills/incident-to-card/SKILL.md +126 -0
  18. package/skills/log-outreach.md +62 -0
  19. package/skills/ship-the-card/SKILL.md +155 -0
  20. package/tool-annotations.js +269 -0
  21. package/tools/billing.js +149 -0
  22. package/tools/email-tools.js +652 -0
  23. package/tools/enterprise-tools.js +651 -0
  24. package/tools/free-search.js +160 -0
  25. package/tools/memory.js +440 -0
  26. package/tools/morning-brief.js +551 -0
  27. package/tools/paper-tools.js +563 -0
  28. package/tools/scheduling.js +322 -0
  29. package/tools/work-board-tools.js +758 -0
  30. package/toolsets/communications.js +276 -0
  31. package/toolsets/crm.js +495 -0
  32. package/toolsets/extensibility.js +1131 -0
  33. package/toolsets/infrastructure.js +757 -0
  34. package/toolsets/intelligence.js +232 -0
  35. package/toolsets/knowledge.js +154 -0
  36. package/toolsets/matrix.js +217 -0
  37. package/toolsets/outreach.js +432 -0
  38. package/toolsets/prospecting.js +314 -0
  39. package/toolsets/revenue/always-loaded.js +341 -0
  40. package/toolsets/revenue/sloan-tools.js +81 -0
  41. package/transport-http.js +505 -0
package/README.md ADDED
@@ -0,0 +1,548 @@
1
+ # @adrata/adrata-mcp
2
+
3
+ Connect Claude Code, Cursor, Windsurf, VS Code, and Claude Desktop to your Adrata CRM workspace via the Model Context Protocol.
4
+
5
+ Three tiers: **Free** (no account needed), **Pro** (API key), **Enterprise** (OAuth workspace connection).
6
+
7
+ ## Two names, one server
8
+
9
+ This package is also published as **[`@adrata/starfield-mcp`](https://www.npmjs.com/package/@adrata/starfield-mcp)**
10
+ (binary `starfield-mcp`), for people wiring a coding agent to their Starfield
11
+ board rather than to the CRM. It is not a fork and not a subset: it depends on
12
+ this package, defaults `ADRATA_MCP_SERVER_NAME` to `Starfield` so the client's
13
+ server list says Starfield, and imports the same `server.js`. Same 233 tools,
14
+ same tiers, same governed-write contract, and nothing to keep in sync.
15
+
16
+ Install whichever name matches what you are doing. If you already have one, you
17
+ do not need the other.
18
+
19
+ ## Installation
20
+
21
+ ### Adrata CLI installer
22
+
23
+ For Claude Code and Codex, use the CLI installer so the assistant gets both
24
+ MCP access and the Adrata operating instructions:
25
+
26
+ ```bash
27
+ adrata login --api-url=https://api.adrata.com --token=<api_key> --workspace=<workspace_id>
28
+ adrata install --target=all --scope=project
29
+ ```
30
+
31
+ The installer writes `.claude/mcp.json`, `.claude/CLAUDE.md`,
32
+ `.codex/config.toml`, and `AGENTS.md` for the current project, plus the bundled
33
+ Agent Skills into `.claude/skills`, `.codex/skills`, and `.agents/skills`. It
34
+ does not embed secrets in the MCP config; the MCP server reads the token from
35
+ `ADRATA_CONFIG_FILE`.
36
+
37
+ Aliases: `adrata gtm install` and `adrata agent install`.
38
+
39
+ **Codex only reads TOML.** Its MCP config lives under `[mcp_servers.<name>]` in
40
+ `~/.codex/config.toml` or `<project>/.codex/config.toml`. A `.codex/mcp.json` is
41
+ ignored — no error, no server, no clue why. The same applies to ChatGPT, which
42
+ is the same product.
43
+
44
+ **Codex also ignores a project `config.toml` in a directory it has not been told
45
+ to trust**, and says nothing about that either. On a fresh clone, answer "Yes,
46
+ allow Codex to work in this folder" on first launch, or add to
47
+ `~/.codex/config.toml`:
48
+
49
+ ```toml
50
+ [projects."/absolute/path/to/your/checkout"]
51
+ trust_level = "trusted"
52
+ ```
53
+
54
+ Skills load in untrusted projects; MCP servers do not. `codex mcp list`, run
55
+ from the project directory, prints exactly what Codex will start — use it to
56
+ confirm rather than guessing from the file.
57
+
58
+ ### Claude Code
59
+
60
+ ```bash
61
+ claude mcp add adrata -- npx -y @adrata/adrata-mcp
62
+ ```
63
+
64
+ Or add to `.claude/mcp.json`:
65
+
66
+ ```json
67
+ {
68
+ "mcpServers": {
69
+ "adrata": {
70
+ "command": "npx",
71
+ "args": ["-y", "@adrata/adrata-mcp"],
72
+ "env": {
73
+ "ADRATA_API_KEY": "ak_your_key_here"
74
+ }
75
+ }
76
+ }
77
+ }
78
+ ```
79
+
80
+ ### Codex CLI / ChatGPT
81
+
82
+ TOML, not JSON. Add to `~/.codex/config.toml` (or `<project>/.codex/config.toml`
83
+ for one repo):
84
+
85
+ ```toml
86
+ [mcp_servers.adrata]
87
+ command = "npx"
88
+ args = ["-y", "@adrata/adrata-mcp"]
89
+
90
+ [mcp_servers.adrata.env]
91
+ ADRATA_API_KEY = "ak_your_key_here"
92
+ ```
93
+
94
+ Then verify from the project directory:
95
+
96
+ ```bash
97
+ codex mcp list # adrata must appear; if it does not, the project is untrusted
98
+ ```
99
+
100
+ ### Cursor
101
+
102
+ Add to `.cursor/mcp.json`:
103
+
104
+ ```json
105
+ {
106
+ "mcpServers": {
107
+ "adrata": {
108
+ "command": "npx",
109
+ "args": ["-y", "@adrata/adrata-mcp"],
110
+ "env": {
111
+ "ADRATA_API_KEY": "ak_your_key_here"
112
+ }
113
+ }
114
+ }
115
+ }
116
+ ```
117
+
118
+ ### Windsurf
119
+
120
+ Add to `.windsurf/mcp.json`:
121
+
122
+ ```json
123
+ {
124
+ "servers": {
125
+ "adrata": {
126
+ "command": "npx",
127
+ "args": ["-y", "@adrata/adrata-mcp"],
128
+ "env": {
129
+ "ADRATA_API_KEY": "ak_your_key_here"
130
+ }
131
+ }
132
+ }
133
+ }
134
+ ```
135
+
136
+ Note: Windsurf uses `"servers"` instead of `"mcpServers"`.
137
+
138
+ ### VS Code
139
+
140
+ Add to `.vscode/mcp.json`:
141
+
142
+ ```json
143
+ {
144
+ "mcpServers": {
145
+ "adrata": {
146
+ "command": "npx",
147
+ "args": ["-y", "@adrata/adrata-mcp"],
148
+ "env": {
149
+ "ADRATA_API_KEY": "ak_your_key_here"
150
+ }
151
+ }
152
+ }
153
+ }
154
+ ```
155
+
156
+ ### Claude Desktop / Cowork
157
+
158
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
159
+
160
+ ```json
161
+ {
162
+ "mcpServers": {
163
+ "adrata": {
164
+ "command": "npx",
165
+ "args": ["-y", "@adrata/adrata-mcp"],
166
+ "env": {
167
+ "ADRATA_API_KEY": "ak_your_key_here"
168
+ }
169
+ }
170
+ }
171
+ }
172
+ ```
173
+
174
+ ## Tiers
175
+
176
+ | Tier | Credentials | What You Get |
177
+ |------|------------|--------------|
178
+ | **Free** | None | Search, email sync, demo scheduling, memory, morning brief teaser |
179
+ | **Pro** | `ADRATA_API_KEY` | + Intelligence, analytics, enrichment, meetings, speedrun, coaching |
180
+ | **Enterprise** | OAuth (`connect_workspace`) | + CRM CRUD, sequences, campaigns, bulk ops, workspace admin |
181
+
182
+ Get your API key from **Settings > API Keys** in Adrata. Enterprise users authenticate via the `connect_workspace` tool or by setting `ADRATA_OAUTH_TOKEN`.
183
+
184
+ ## Tools by Tier
185
+
186
+ ### Free Tier (no account needed)
187
+
188
+ | Tool | Description |
189
+ |------|-------------|
190
+ | `find_company` | Search company profile using AI knowledge |
191
+ | `find_person` | Search person profile using AI knowledge |
192
+ | `search_companies` | Search companies in CRM |
193
+ | `search_people` | Search people in CRM |
194
+ | `search_leads` | Search leads |
195
+ | `search_emails` | Search emails |
196
+ | `get_email` | Get email by ID |
197
+ | `count_emails` | Count emails matching criteria |
198
+ | `check_inbox` | Check inbox for new emails |
199
+ | `find_or_create_person` | Find or create a person record |
200
+ | `find_or_create_company` | Find or create a company record |
201
+ | `get_demo_availability` | Check demo availability slots |
202
+ | `schedule_demo` | Schedule a product demo |
203
+ | `describe_fields` | Schema introspection for entity fields |
204
+ | `list_custom_fields` | List available custom fields |
205
+ | `save_memory` | Store a fact or insight (local in free tier) |
206
+ | `recall` | Search saved memories |
207
+ | `who_am_i` | View user profile and usage stats |
208
+ | `forget` | Remove a saved memory |
209
+ | `morning_brief` | Daily briefing (teaser in free tier, full in pro+) |
210
+ | `upgrade_account` | Open signup/upgrade page |
211
+ | `check_subscription` | Check current plan and usage |
212
+ | `connect_workspace` | Connect Adrata workspace via OAuth |
213
+ | `disconnect_workspace` | Disconnect workspace |
214
+ | `workspace_status` | Check workspace connection status |
215
+ | `inspect_provider_catalog` | Inspect available integration providers |
216
+ | `list_provider_endpoints` | Inspect provider endpoints/actions before workflow drafting |
217
+ | `validate_integration_manifest` | Validate a custom integration manifest |
218
+ | `validate_extension_manifest` | Validate a custom extension manifest |
219
+ | `draft_workflow` | Draft a headless workflow manifest |
220
+ | `validate_workflow_draft` | Validate workflow permissions, audit, policy, and replay rules |
221
+ | `dry_run_workflow` | Dry-run or locally plan a workflow execution |
222
+ | `adrata_api_catalog` | Explain governed full-platform API access |
223
+ | `inspect_provider_catalog` | Inspect available integration providers |
224
+ | `list_provider_endpoints` | Inspect provider endpoints/actions before workflow drafting |
225
+ | `validate_integration_manifest` | Validate a custom integration manifest |
226
+ | `validate_extension_manifest` | Validate a custom extension manifest |
227
+ | `draft_workflow` | Draft a headless workflow manifest |
228
+ | `validate_workflow_draft` | Validate workflow permissions, audit, policy, and replay rules |
229
+ | `dry_run_workflow` | Dry-run or locally plan a workflow execution |
230
+ | `list_toolsets` | List available composite toolsets |
231
+ | `enable_toolset` | Enable a composite toolset |
232
+
233
+ ### Pro Tier (requires API key)
234
+
235
+ All free tools plus:
236
+
237
+ | Tool | Description |
238
+ |------|-------------|
239
+ | `get_company` | Get full company details |
240
+ | `get_person` | Get full person details |
241
+ | `get_opportunity` | Get opportunity details |
242
+ | `get_action` | Get action details |
243
+ | `enrich_company` | AI-powered company enrichment |
244
+ | `enrich_person` | AI-powered contact enrichment |
245
+ | `get_intent_signals` | Buying intent signals for a company |
246
+ | `list_customer_signals` | First-party customer signals (the store live plays fire from) for the workspace or a subject |
247
+ | `get_deal_authority` | Map decision makers and authority |
248
+ | `get_competitor_intel` | Competitive intelligence brief |
249
+ | `score_company_icp` | Score company against ideal customer profile |
250
+ | `get_icp_distribution` | ICP score distribution analytics |
251
+ | `get_pipeline_metrics` | Pipeline analytics dashboard |
252
+ | `get_forecast_data` | Revenue forecast data |
253
+ | `get_activity_summary` | Activity summary for a time period |
254
+ | `count_records` | Count records by entity type |
255
+ | `get_priority_pursuits` | Evidence-ranked daily account and next-move list |
256
+ | `get_speedrun_list` | Legacy alias for `get_priority_pursuits` |
257
+ | `list_meetings` | List scheduled meetings |
258
+ | `get_meeting` | Get meeting details |
259
+ | `get_meeting_summary` | AI-generated meeting summary |
260
+ | `get_meeting_action_items` | Action items from a meeting |
261
+ | `list_actions` | List actions |
262
+ | `list_overdue_actions` | List overdue actions |
263
+ | `list_today_actions` | List actions due today |
264
+ | `list_notes` | List notes for an entity |
265
+ | `log_interaction` | Log a sales interaction |
266
+ | `qualify_company` | Composite: full company qualification |
267
+ | `research_company` | Composite: deep company research |
268
+ | `research_person` | Composite: deep person research |
269
+ | `discover_prospects` | Composite: find new prospects |
270
+ | `get_next_contacts` | Composite: next best contacts to reach |
271
+ | `get_competitive_intel` | Composite: competitive analysis |
272
+ | `get_meeting_brief` | Composite: pre-meeting intelligence |
273
+ | `get_deal_coaching` | Composite: deal coaching insights |
274
+ | `get_signals_dashboard` | Composite: signals overview |
275
+ | `get_forecast` | Composite: forecast summary |
276
+ | `draft_email` | Composite: draft a sales email |
277
+ | `get_outreach_analytics` | Composite: outreach performance |
278
+ | `get_network_paths` | Composite: relationship paths |
279
+ | `search_emails_composite` | Composite: advanced email search |
280
+ | `get_email_thread` | Composite: full email thread |
281
+ | `find_intro_path` | Find a warm relationship path |
282
+ | `get_network_stats` | Network coverage and intro health |
283
+ | `list_webhook_events` | Supported webhook event catalog |
284
+
285
+ ### Enterprise Tier (requires OAuth)
286
+
287
+ All free and pro tools plus:
288
+
289
+ | Tool | Description |
290
+ |------|-------------|
291
+ | `create_company` | Create a company record |
292
+ | `update_company` | Update company fields |
293
+ | `delete_company` | Delete a company |
294
+ | `create_person` | Create a person record |
295
+ | `update_person` | Update person fields |
296
+ | `delete_person` | Delete a person |
297
+ | `create_opportunity` | Create an opportunity |
298
+ | `update_opportunity` | Update opportunity fields |
299
+ | `delete_opportunity` | Delete an opportunity |
300
+ | `create_action` | Create an action/task |
301
+ | `update_action` | Update an action |
302
+ | `complete_action` | Mark an action complete |
303
+ | `delete_action` | Delete an action |
304
+ | `create_note` | Create a note |
305
+ | `update_note` | Update a note |
306
+ | `delete_note` | Delete a note |
307
+ | `get_company_people` | List people at a company |
308
+ | `get_company_opportunities` | List opportunities for a company |
309
+ | `get_company_actions` | List actions for a company |
310
+ | `search_opportunities` | Search opportunities |
311
+ | `list_buyer_groups` | List buyer groups |
312
+ | `get_buyer_group` | Get buyer group details |
313
+ | `create_buyer_group` | Create a buyer group |
314
+ | `add_buyer_group_member` | Add member to buyer group |
315
+ | `get_buyer_group_members` | List buyer group members |
316
+ | `list_intro_requests` | List tracked warm intro requests |
317
+ | `get_intro_pipeline` | View the warm intro pipeline |
318
+ | `create_intro_request` | Create a tracked warm intro request |
319
+ | `update_intro_request` | Update intro request status |
320
+ | `list_agent_tasks` | List long-running agent/background tasks |
321
+ | `create_agent_task` | Create a long-running agent/background task |
322
+ | `get_agent_task` | Get task status and result |
323
+ | `cancel_agent_task` | Cancel a running task |
324
+ | `adrata_api_request` | Governed low-level request to allowlisted, non-sensitive platform APIs |
325
+ | `adrata_ai_tool_catalog` | List the AI CRM tools Adrata chat can use |
326
+ | `adrata_ai_tool_execute` | Execute the same governed ToolDispatcher path used by Adrata chat |
327
+ | `get_account_read` | Grounded no-loss account/deal read via the chat ToolDispatcher |
328
+ | `rank_paths_to_power` | Ranked warm/network paths to decision makers via the chat ToolDispatcher |
329
+ | `recommend_deal_move` | Read-only no-loss next deal move recommendation via the chat ToolDispatcher |
330
+ | `list_external_pipelines` | List refreshable Channels such as YC, Techstars, CSV, LinkedIn, and sequence sources |
331
+ | `list_external_pipeline_members` | Preview Channel members before import |
332
+ | `import_external_pipeline_members` | Import Channel members through Adrata bulk import |
333
+ | `list_external_companies` | Query nightly-refreshed external company catalogs |
334
+ | `import_external_companies` | Import selected external catalog companies |
335
+ | `rank_companies_by_icp` | Rank imported companies against the workspace ICP profile |
336
+ | `rank_people_by_icp` | Rank imported people against the workspace ICP profile (title/persona + firmographics) |
337
+ | `check_batch_import_status` | Poll bulk import progress and enrichment status |
338
+ | `move_pipeline_card` | Move a pipeline card and publish realtime UI updates |
339
+ | `list_webhooks` | List outbound webhook subscriptions |
340
+ | `create_webhook` | Create a webhook subscription |
341
+ | `update_webhook` | Update webhook URL, events, or filters |
342
+ | `delete_webhook` | Delete a webhook subscription |
343
+ | `test_webhook` | Queue a signed webhook test event |
344
+ | `list_webhook_deliveries` | List delivery attempts |
345
+ | `get_webhook_delivery` | Inspect a delivery attempt |
346
+ | `replay_webhook_delivery` | Replay a delivery attempt |
347
+ | `test_provider_credential` | Run a dry-run or live credential health test with policy/audit metadata |
348
+ | `request_deployment` | Request custom integration or extension deployment after manifest validation |
349
+ | `request_workflow_deployment` | Request workflow deployment after a prior dry-run id |
350
+ | `replay_workflow_run` | Dry-run or request replay for a workflow run |
351
+ | `list_campaigns` | List email campaigns |
352
+ | `get_campaign` | Get campaign details |
353
+ | `list_sequences` | List email sequences |
354
+ | `get_sequence` | Get sequence details |
355
+ | `list_users` | List workspace users |
356
+ | `get_user` | Get user details |
357
+ | `get_current_user` | Get current authenticated user |
358
+ | `send_email` | Send an email |
359
+ | `reply_to_email` | Reply to an email thread |
360
+ | `manage_sequences` | Manage sequence enrollment |
361
+ | `bulk_import` | Bulk import records from CSV |
362
+ | `export_data` | Export records as JSON/CSV |
363
+ | `manage_custom_fields` | Manage custom field definitions |
364
+ | `get_workspace_settings` | View workspace configuration |
365
+ | `manage_company` | Composite: full company management |
366
+ | `manage_person` | Composite: full person management |
367
+ | `manage_opportunity` | Composite: full opportunity management |
368
+ | `manage_activity` | Composite: full activity management |
369
+ | `manage_buyer_group` | Composite: full buyer group management |
370
+ | `get_action_history` | Composite: action history timeline |
371
+ | `make_call` | Composite: initiate a call |
372
+ | `send_sms` | Composite: send SMS message |
373
+ | `get_call_transcript` | Composite: retrieve call transcript |
374
+ | `check_calendar` | Composite: check calendar availability |
375
+ | `schedule_meeting` | Composite: schedule a meeting |
376
+ | `manage_domains` | Composite: email domain management |
377
+ | `manage_mailboxes` | Composite: mailbox configuration |
378
+ | `get_deliverability` | Composite: email deliverability metrics |
379
+ | `connect_provider` | Composite: connect email provider |
380
+ | `manage_workspace` | Composite: workspace settings |
381
+ | `manage_data` | Composite: data operations |
382
+
383
+ ## Agent API Bridge Governance
384
+
385
+ `adrata_api_request` is a broad fallback for platform API access. Prefer targeted
386
+ tools such as `adrata_ai_tool_execute`, `move_pipeline_card`, webhook tools,
387
+ integration tools, and workspace/user tools when they exist.
388
+
389
+ The bridge enforces least-privilege deny rules for sensitive administrative
390
+ surfaces even when those route families are present in the platform allowlist:
391
+ `/api/v1/billing`, `/api/v1/api-keys`, `/api/v1/observability`,
392
+ `/api/v1/users`, `/api/v1/integrations`, `/api/v1/custom-integrations`,
393
+ and `/api/v1/webhooks`.
394
+
395
+ Write requests through `adrata_api_request` default to dry-run. A live
396
+ `POST`, `PUT`, `PATCH`, or `DELETE` requires `dryRun:false`, `approved:true`,
397
+ a non-empty `reason`, and an `idempotencyKey`; the MCP bridge forwards the
398
+ reason, actor, and idempotency metadata as request headers.
399
+
400
+ Known gap: the MCP bridge now applies a consistent approval/idempotency envelope,
401
+ but not every downstream API endpoint has a uniform server-side envelope yet.
402
+ Treat `adrata_api_request` as a governed escape hatch and use higher-level MCP
403
+ tools for privileged operations.
404
+
405
+ ## Custom Fields
406
+
407
+ Companies, People, and Opportunities support `customFields` -- a JSONB object that gets merged on update. Add any key-value pairs without losing existing data.
408
+
409
+ ```
410
+ "Update this company's customFields with outreach_status: contacted"
411
+ ```
412
+
413
+ ## Action Metadata
414
+
415
+ Actions support `metadata` -- a JSONB object for type-specific data. Use it for LinkedIn message copy, call notes, meeting attendees, etc.
416
+
417
+ ```
418
+ "Log a linkedin_connection_request action for this person with metadata containing the message I sent"
419
+ ```
420
+
421
+ ## Environment Variables
422
+
423
+ | Variable | Required | Default | Description |
424
+ |----------|----------|---------|-------------|
425
+ | `ADRATA_API_KEY` | No | -- | Your API key from Settings > API Keys. Enables pro tier. |
426
+ | `ADRATA_OAUTH_TOKEN` | No | -- | OAuth bearer token. Enables enterprise tier. |
427
+ | `ADRATA_API_URL` | No | `https://api.adrata.com` | API base URL |
428
+ | `ADRATA_MCP_SERVER_NAME` | No | `@adrata/adrata-mcp` | Display name reported in `serverInfo`. `@adrata/starfield-mcp` sets it to `Starfield`. Does not change the tool prefix, which comes from your client's config key. |
429
+ | `ADRATA_MCP_TRANSPORT` | No | `stdio` | Transport: `stdio` or `http` |
430
+ | `ADRATA_MCP_PORT` | No | `3100` | Port for HTTP transport |
431
+ | `ADRATA_MCP_CORS_ORIGINS` | No | `*` | Comma-separated CORS origins for HTTP transport |
432
+ | `ADRATA_MCP_REQUIRE_AUTH` | No | `true` | Require Bearer auth for HTTP `/mcp`; set `false` only for isolated local testing |
433
+ | `ADRATA_MCP_RESOURCE` | No | `${AS}/api/v1/mcp` | RFC 8707 canonical resource URI this server binds tokens to |
434
+ | `ADRATA_MCP_AUTHORIZATION_SERVER` | No | `ADRATA_API_URL` | Authorization server(s) advertised in RFC 9728 metadata |
435
+ | `ADRATA_MCP_ACCEPTED_AUDIENCES` | No | `adrata,<resource>` | Extra token audiences accepted by the resource server |
436
+ | `ADRATA_MCP_AUDIENCE_ENFORCEMENT` | No | `lenient` | `strict` rejects JWTs that carry no `aud` claim at all |
437
+ | `ADRATA_MCP_ENABLED_DOMAINS` | No | (all) | Least-privilege scoping: comma list of tool packs (e.g. `crm,email`) |
438
+ | `ADRATA_MCP_CLIENT_ID` | No | dynamic registration | Operator-provisioned public OAuth client override. Most installations should leave this unset. |
439
+ | `ADRATA_MCP_PRINT_AUTH_URL` | No | `0` | Set to `1` to print the authorization URL for headless/manual browser use. |
440
+
441
+ ## Authorization (MCP 2025-06-18 spec)
442
+
443
+ The hosted HTTP transport is an OAuth 2.1 **resource server** hardened to the
444
+ 2025 MCP authorization spec:
445
+
446
+ - **OAuth 2.1 + PKCE (S256).** Browser `connect_workspace` flow with a
447
+ short-lived (15 min) access token and a rotating refresh token.
448
+ - **RFC 8707 Resource Indicators.** The client sends `resource` on the
449
+ authorize + token requests; the authorization server binds the token's
450
+ `aud` to that MCP resource.
451
+ - **No token passthrough.** Every presented bearer token is checked against
452
+ this resource's audience *before* it can reach any tool or the upstream API.
453
+ A token minted for a different audience is rejected with `401 invalid_token`
454
+ and a `WWW-Authenticate` challenge pointing at the resource metadata.
455
+ - **RFC 9728 Protected Resource Metadata.** Served unauthenticated at
456
+ `GET /.well-known/oauth-protected-resource`, describing this resource and its
457
+ authorization server(s) so clients can discover how to authenticate.
458
+ - **Honest tool annotations.** Every tool advertises truthful
459
+ `readOnly` / `destructive` / `idempotent` / `openWorld` hints plus a `domain`
460
+ tag. Write and destructive tools are confirmation-gated (host prompt) and are
461
+ additionally tier-gated + audit-logged server-side; the governed API bridge
462
+ requires `dryRun:false` + `approved:true` + `reason` + `idempotencyKey` for
463
+ any live write.
464
+ - **Confused-deputy / tool-poisoning defenses.** Annotations and descriptions
465
+ are derived from real behaviour, never from untrusted model input; audience
466
+ binding prevents a token issued for client A from being replayed by client B.
467
+ - **Scoped per-domain tool packs.** Set `ADRATA_MCP_ENABLED_DOMAINS` to grant a
468
+ least-privilege subset (e.g. `crm,email`); out-of-scope tools are refused at
469
+ dispatch. Workspace-lifecycle tools stay available in every scope.
470
+
471
+ ## MCP Registry
472
+
473
+ This server ships a `server.json` manifest for the official
474
+ [MCP Registry](https://registry.modelcontextprotocol.io).
475
+
476
+ To publish/update the listing:
477
+
478
+ ```bash
479
+ # 1. Install the registry publisher CLI
480
+ brew install mcp-publisher # or: go install github.com/modelcontextprotocol/registry/cmd/publisher@latest
481
+
482
+ # 2. Authenticate the com.adrata namespace (GitHub or DNS-verified)
483
+ mcp-publisher login github
484
+
485
+ # 3. Validate and publish from code/mcp/
486
+ mcp-publisher publish ./server.json
487
+ ```
488
+
489
+ The namespace `com.adrata/*` is verified via the `adrata/adrata` GitHub repo.
490
+ Bump `version` in both `server.json` and `package.json` before republishing.
491
+
492
+ ## Enterprise Setup: OAuth Flow
493
+
494
+ Enterprise authentication uses the `connect_workspace` tool for a browser-based OAuth flow:
495
+
496
+ 1. Call `connect_workspace` in your AI tool
497
+ 2. The MCP package dynamically registers a per-attempt native/public client (no embedded secret)
498
+ 3. A browser opens Adrata sign-in and a dark-mode workspace consent screen
499
+ 4. Adrata returns to an exact IP-literal loopback callback protected by state + PKCE
500
+ 5. Tokens and the issued client ID are stored encrypted in `~/.adrata/tokens.json`
501
+ 6. Rotating refresh tokens keep the session alive and preserve the MCP resource audience
502
+
503
+ Alternatively, set `ADRATA_OAUTH_TOKEN` directly for CI/CD or scripted environments.
504
+
505
+ ## Troubleshooting
506
+
507
+ ### Server fails to start
508
+
509
+ - Verify Node.js >= 18: `node --version`
510
+ - Check npx can resolve the package: `npx -y @adrata/adrata-mcp --version`
511
+ - Look for error messages in the AI tool's MCP server logs
512
+
513
+ ### "Tool requires pro tier" message
514
+
515
+ - Set `ADRATA_API_KEY` in the env config of your MCP server definition
516
+ - Get your key from Settings > API Keys in Adrata
517
+ - Restart the MCP server after adding the key
518
+
519
+ ### "Tool requires enterprise tier" message
520
+
521
+ - Run `connect_workspace` to authenticate via OAuth
522
+ - Or set `ADRATA_OAUTH_TOKEN` in the env config
523
+ - Enterprise requires an active Adrata Enterprise subscription
524
+
525
+ ### OAuth token expired
526
+
527
+ - The server auto-refreshes stored tokens from `~/.adrata/tokens.json`
528
+ - If refresh fails, run `connect_workspace` again
529
+ - Delete `~/.adrata/tokens.json` to start fresh
530
+
531
+ ### Tools return empty results
532
+
533
+ - Verify your API key has access to the workspace
534
+ - Check that the entity exists in your CRM
535
+ - For enterprise tools, confirm your OAuth token has the required scopes
536
+
537
+ ### HTTP transport mode
538
+
539
+ - Set `ADRATA_MCP_TRANSPORT=http` for Streamable HTTP transport
540
+ - Server listens on port 3100 by default (configurable via `ADRATA_MCP_PORT`)
541
+ - Hosted and local HTTP mode require `Authorization: Bearer ...` by default
542
+ - Configure CORS origins if calling from a web client
543
+
544
+ ### Rate limiting
545
+
546
+ - Free tier: subject to standard rate limits
547
+ - Pro tier: higher rate limits per API key
548
+ - Enterprise tier: workspace-level rate limits based on plan