@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.
- package/README.md +548 -0
- package/access/auth.js +289 -0
- package/access/oauth.js +1059 -0
- package/access/resource-metadata.js +167 -0
- package/access/tiers.js +422 -0
- package/analytics.js +634 -0
- package/api-bridge.js +499 -0
- package/governance/money.js +141 -0
- package/output-formatter.js +589 -0
- package/package.json +68 -0
- package/resources.js +246 -0
- package/security.js +690 -0
- package/server.js +2139 -0
- package/server.json +55 -0
- package/skills/backlog-triage/SKILL.md +115 -0
- package/skills/board-review/SKILL.md +96 -0
- package/skills/incident-to-card/SKILL.md +126 -0
- package/skills/log-outreach.md +62 -0
- package/skills/ship-the-card/SKILL.md +155 -0
- package/tool-annotations.js +269 -0
- package/tools/billing.js +149 -0
- package/tools/email-tools.js +652 -0
- package/tools/enterprise-tools.js +651 -0
- package/tools/free-search.js +160 -0
- package/tools/memory.js +440 -0
- package/tools/morning-brief.js +551 -0
- package/tools/paper-tools.js +563 -0
- package/tools/scheduling.js +322 -0
- package/tools/work-board-tools.js +758 -0
- package/toolsets/communications.js +276 -0
- package/toolsets/crm.js +495 -0
- package/toolsets/extensibility.js +1131 -0
- package/toolsets/infrastructure.js +757 -0
- package/toolsets/intelligence.js +232 -0
- package/toolsets/knowledge.js +154 -0
- package/toolsets/matrix.js +217 -0
- package/toolsets/outreach.js +432 -0
- package/toolsets/prospecting.js +314 -0
- package/toolsets/revenue/always-loaded.js +341 -0
- package/toolsets/revenue/sloan-tools.js +81 -0
- package/transport-http.js +505 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Honest MCP tool annotations + per-domain scoping for the Adrata MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Two jobs:
|
|
5
|
+
* 1. Annotate every exposed tool with the MCP `ToolAnnotations` behaviour
|
|
6
|
+
* hints (readOnlyHint / destructiveHint / idempotentHint / openWorldHint)
|
|
7
|
+
* so a host (Claude, Cursor, ...) can truthfully decide what needs
|
|
8
|
+
* confirmation. These hints are advisory per the MCP spec and MUST be
|
|
9
|
+
* treated as untrusted by clients — we derive them from the tool's real
|
|
10
|
+
* behaviour, never from a model-supplied description.
|
|
11
|
+
* 2. Tag each tool with a domain "pack" (crm, email, calendar, enrichment,
|
|
12
|
+
* ...) so a client can request least-privilege scopes. When
|
|
13
|
+
* ADRATA_MCP_ENABLED_DOMAINS is set, tools outside the enabled packs are
|
|
14
|
+
* refused at dispatch — a lightweight scoped-tool-pack enforcement that
|
|
15
|
+
* avoids shipping N separate servers.
|
|
16
|
+
*
|
|
17
|
+
* Pure/stateless so it is unit-testable.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Domain packs
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Explicit tool -> domain overrides. Anything not listed falls back to the
|
|
26
|
+
* keyword/prefix heuristic in getToolDomain().
|
|
27
|
+
*/
|
|
28
|
+
const DOMAIN_OVERRIDES = {
|
|
29
|
+
// Meta / workspace lifecycle — always available regardless of scope.
|
|
30
|
+
connect_workspace: 'workspace',
|
|
31
|
+
disconnect_workspace: 'workspace',
|
|
32
|
+
workspace_status: 'workspace',
|
|
33
|
+
list_workspaces: 'workspace',
|
|
34
|
+
switch_workspace: 'workspace',
|
|
35
|
+
get_workspace_settings: 'workspace',
|
|
36
|
+
list_toolsets: 'workspace',
|
|
37
|
+
enable_toolset: 'workspace',
|
|
38
|
+
who_am_i: 'workspace',
|
|
39
|
+
get_current_user: 'workspace',
|
|
40
|
+
|
|
41
|
+
// Governed API bridge.
|
|
42
|
+
adrata_api_catalog: 'bridge',
|
|
43
|
+
adrata_api_request: 'bridge',
|
|
44
|
+
adrata_ai_tool_catalog: 'bridge',
|
|
45
|
+
adrata_ai_tool_execute: 'bridge',
|
|
46
|
+
|
|
47
|
+
// Enrichment / external intelligence.
|
|
48
|
+
enrich_company: 'enrichment',
|
|
49
|
+
enrich_person: 'enrichment',
|
|
50
|
+
get_intent_signals: 'enrichment',
|
|
51
|
+
list_customer_signals: 'enrichment',
|
|
52
|
+
get_competitor_intel: 'enrichment',
|
|
53
|
+
get_company_firmographics: 'enrichment',
|
|
54
|
+
score_company_icp: 'intelligence',
|
|
55
|
+
list_icp_profiles: 'intelligence',
|
|
56
|
+
rank_companies_by_icp: 'intelligence',
|
|
57
|
+
rank_people_by_icp: 'intelligence',
|
|
58
|
+
get_icp_distribution: 'intelligence',
|
|
59
|
+
get_deal_authority: 'intelligence',
|
|
60
|
+
rank_paths_to_power: 'intelligence',
|
|
61
|
+
recommend_deal_move: 'intelligence',
|
|
62
|
+
get_account_read: 'intelligence',
|
|
63
|
+
build_pursuit_command_center: 'intelligence',
|
|
64
|
+
get_pipeline_metrics: 'intelligence',
|
|
65
|
+
get_forecast_data: 'intelligence',
|
|
66
|
+
get_speedrun_list: 'intelligence',
|
|
67
|
+
get_priority_pursuits: 'intelligence',
|
|
68
|
+
morning_brief: 'intelligence',
|
|
69
|
+
|
|
70
|
+
// Networking / warm intros.
|
|
71
|
+
find_intro_path: 'network',
|
|
72
|
+
get_network_stats: 'network',
|
|
73
|
+
create_intro_request: 'network',
|
|
74
|
+
update_intro_request: 'network',
|
|
75
|
+
list_intro_requests: 'network',
|
|
76
|
+
get_intro_pipeline: 'network',
|
|
77
|
+
|
|
78
|
+
// Meetings / calendar.
|
|
79
|
+
schedule_demo: 'calendar',
|
|
80
|
+
schedule_meeting: 'calendar',
|
|
81
|
+
get_demo_availability: 'calendar',
|
|
82
|
+
list_meetings: 'meetings',
|
|
83
|
+
get_meeting: 'meetings',
|
|
84
|
+
get_meeting_summary: 'meetings',
|
|
85
|
+
get_meeting_action_items: 'meetings',
|
|
86
|
+
|
|
87
|
+
// Memory.
|
|
88
|
+
save_memory: 'memory',
|
|
89
|
+
recall: 'memory',
|
|
90
|
+
forget: 'memory',
|
|
91
|
+
|
|
92
|
+
// Billing.
|
|
93
|
+
upgrade_account: 'billing',
|
|
94
|
+
check_subscription: 'billing',
|
|
95
|
+
|
|
96
|
+
// Analytics.
|
|
97
|
+
get_mcp_analytics: 'analytics',
|
|
98
|
+
track_conversion: 'analytics',
|
|
99
|
+
|
|
100
|
+
// Finance: the customer's own ERP invoices / installed base. Its own pack so
|
|
101
|
+
// a least-privilege scope can grant CRM reads without granting revenue data.
|
|
102
|
+
// get_company_invoices would otherwise fall through to the 'crm' keyword rule.
|
|
103
|
+
get_installed_base: 'finance',
|
|
104
|
+
get_company_invoices: 'finance',
|
|
105
|
+
|
|
106
|
+
// Adrata Cloud: the bitemporal record substrate read.
|
|
107
|
+
get_cloud_records: 'cloud',
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const DOMAIN_PREFIX_RULES = [
|
|
111
|
+
[/^(create_email_account|list_email_accounts|warmup_email|get_email_health)/, 'infra'],
|
|
112
|
+
[/^(search_domains|purchase_domain|setup_domain|verify_domain|list_domains)/, 'infra'],
|
|
113
|
+
[/^(create_sequence|list_sequences|get_sequence|add_sequence_step|activate_sequence|pause_sequence|get_sequence_analytics|enroll_contacts|list_campaigns|get_campaign)/, 'sequences'],
|
|
114
|
+
[/^(search_emails|get_email|count_emails|check_inbox|log_interaction)/, 'email'],
|
|
115
|
+
[/webhook/, 'webhooks'],
|
|
116
|
+
[/(buyer_group)/, 'buyergroup'],
|
|
117
|
+
[/^(create_action|update_action|complete_action|delete_action|get_action|list_actions|list_overdue_actions|list_today_actions|get_activity_summary)/, 'actions'],
|
|
118
|
+
[/note/, 'notes'],
|
|
119
|
+
[/opportunit|move_pipeline_card/, 'pipeline'],
|
|
120
|
+
[/agent_task/, 'agent'],
|
|
121
|
+
[/(external_pipeline|external_companies|import_external|check_batch_import|bulk_import|export_data)/, 'admin'],
|
|
122
|
+
[/(custom_field|describe_fields|manage_data|manage_workspace)/, 'admin'],
|
|
123
|
+
[/(company|companies)/, 'crm'],
|
|
124
|
+
[/(person|people|lead|contact)/, 'crm'],
|
|
125
|
+
[/^search/, 'search'],
|
|
126
|
+
[/^find/, 'search'],
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
/** Domains that are always callable regardless of ADRATA_MCP_ENABLED_DOMAINS. */
|
|
130
|
+
const ALWAYS_ENABLED_DOMAINS = new Set(['workspace', 'billing']);
|
|
131
|
+
|
|
132
|
+
/** Resolve the domain pack for a tool. */
|
|
133
|
+
export function getToolDomain(name) {
|
|
134
|
+
if (DOMAIN_OVERRIDES[name]) return DOMAIN_OVERRIDES[name];
|
|
135
|
+
for (const [re, domain] of DOMAIN_PREFIX_RULES) {
|
|
136
|
+
if (re.test(name)) return domain;
|
|
137
|
+
}
|
|
138
|
+
return 'general';
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Enforce per-domain scoping. Returns { allowed } or { allowed:false, reason }.
|
|
143
|
+
* Enabled only when ADRATA_MCP_ENABLED_DOMAINS is set (comma list of packs).
|
|
144
|
+
*/
|
|
145
|
+
export function checkDomainScope(name) {
|
|
146
|
+
const raw = process.env.ADRATA_MCP_ENABLED_DOMAINS;
|
|
147
|
+
if (!raw) return { allowed: true };
|
|
148
|
+
const enabled = new Set(raw.split(',').map(s => s.trim()).filter(Boolean));
|
|
149
|
+
const domain = getToolDomain(name);
|
|
150
|
+
if (ALWAYS_ENABLED_DOMAINS.has(domain) || enabled.has(domain)) return { allowed: true };
|
|
151
|
+
return { allowed: false, reason: 'domain_not_in_scope', domain, enabled: [...enabled] };
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ---------------------------------------------------------------------------
|
|
155
|
+
// Behaviour classification (readOnly / destructive / idempotent / openWorld)
|
|
156
|
+
// ---------------------------------------------------------------------------
|
|
157
|
+
|
|
158
|
+
// Tools that mutate but do not read (idempotent updates vs. creates vs. deletes).
|
|
159
|
+
//
|
|
160
|
+
// Destructive is derived from a PATTERN first, so every future `delete_*`,
|
|
161
|
+
// `bulk_delete_*`, `purchase_*` (irreversible spend) or `*send_email`
|
|
162
|
+
// (irreversible external effect) tool is destructive by construction. The
|
|
163
|
+
// explicit set below covers names the pattern cannot see (mid-name deletes
|
|
164
|
+
// like paper_delete_document, revokes, composite manage_* delete actions).
|
|
165
|
+
const DESTRUCTIVE_PATTERN = /^(delete_|bulk_delete_|purchase_)|send_email$/;
|
|
166
|
+
|
|
167
|
+
const DESTRUCTIVE = new Set([
|
|
168
|
+
'delete_company', 'delete_person', 'delete_opportunity', 'delete_action',
|
|
169
|
+
'delete_note', 'delete_webhook', 'disconnect_workspace', 'forget',
|
|
170
|
+
// Buyer rooms. delete_buyer_group cascades to the room's member seats, and
|
|
171
|
+
// bulk_delete_buyer_groups does that for up to 50 rooms in one call.
|
|
172
|
+
'delete_buyer_group', 'bulk_delete_buyer_groups', 'remove_buyer_group_member',
|
|
173
|
+
// Paper: mid-name delete + share revocation (cuts off external access).
|
|
174
|
+
'paper_delete_document', 'paper_revoke_share',
|
|
175
|
+
// The composite manage_* tools each expose a `delete` action. They were
|
|
176
|
+
// previously unclassified, so isReadOnly() fell through to a false
|
|
177
|
+
// destructiveHint — a host would not have confirmation-gated a delete.
|
|
178
|
+
'manage_company', 'manage_person', 'manage_opportunity', 'manage_activity',
|
|
179
|
+
'manage_buyer_group',
|
|
180
|
+
]);
|
|
181
|
+
|
|
182
|
+
/** True when a tool is destructive (irreversible delete, spend, or send). */
|
|
183
|
+
export function isDestructive(name) {
|
|
184
|
+
return DESTRUCTIVE.has(name) || DESTRUCTIVE_PATTERN.test(name);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Non-read tools that are safe to retry (PATCH/PUT semantics, toggles).
|
|
188
|
+
const IDEMPOTENT_WRITES = new Set([
|
|
189
|
+
'update_company', 'update_person', 'update_opportunity', 'update_action',
|
|
190
|
+
'update_note', 'update_webhook', 'update_intro_request', 'complete_action',
|
|
191
|
+
'pause_sequence', 'activate_sequence', 'verify_domain', 'move_pipeline_card',
|
|
192
|
+
'add_to_company_list', 'find_or_create_person', 'find_or_create_company',
|
|
193
|
+
'save_memory', 'manage_custom_fields', 'build_pursuit_command_center',
|
|
194
|
+
'update_buyer_group', 'update_buyer_group_member',
|
|
195
|
+
]);
|
|
196
|
+
|
|
197
|
+
// Non-read tools that create new state / have side effects each call.
|
|
198
|
+
const NON_IDEMPOTENT_WRITES = new Set([
|
|
199
|
+
'create_company', 'create_person', 'create_opportunity', 'create_action',
|
|
200
|
+
'create_note', 'create_webhook', 'create_buyer_group', 'add_buyer_group_member',
|
|
201
|
+
'create_company_list', 'create_intro_request', 'create_sequence',
|
|
202
|
+
'add_sequence_step', 'enroll_contacts', 'create_email_account',
|
|
203
|
+
'create_agent_task', 'cancel_agent_task', 'bulk_import', 'import_external_companies',
|
|
204
|
+
'import_external_pipeline_members', 'purchase_domain', 'setup_domain',
|
|
205
|
+
'warmup_email', 'schedule_demo', 'schedule_meeting', 'connect_workspace',
|
|
206
|
+
'enable_toolset', 'track_conversion', 'log_interaction', 'test_webhook',
|
|
207
|
+
'replay_webhook_delivery', 'upgrade_account',
|
|
208
|
+
]);
|
|
209
|
+
|
|
210
|
+
// Tools that reach beyond the workspace (external enrichment, web, providers).
|
|
211
|
+
const OPEN_WORLD = new Set([
|
|
212
|
+
'enrich_company', 'enrich_person', 'get_intent_signals', 'get_competitor_intel',
|
|
213
|
+
'get_company_firmographics', 'search_domains', 'purchase_domain',
|
|
214
|
+
'find_intro_path', 'search_leads', 'get_demo_availability', 'schedule_demo',
|
|
215
|
+
]);
|
|
216
|
+
|
|
217
|
+
/** True when a tool only reads state. */
|
|
218
|
+
function isReadOnly(name) {
|
|
219
|
+
if (isDestructive(name) || IDEMPOTENT_WRITES.has(name) || NON_IDEMPOTENT_WRITES.has(name)) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
return /^(get_|list_|search_|find_(?!or_create)|count_|describe_|check_|inspect_|rank_|score_|who_am_i|recall|workspace_status|morning_brief|export_data)/.test(name)
|
|
223
|
+
|| name.endsWith('_catalog')
|
|
224
|
+
|| name.endsWith('_analytics')
|
|
225
|
+
|| name.endsWith('_status');
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Build honest MCP annotations for a tool. Derived only from the tool's real
|
|
230
|
+
* behaviour class + domain — NEVER from an untrusted description string.
|
|
231
|
+
*
|
|
232
|
+
* @param {string} name
|
|
233
|
+
* @param {string} [description]
|
|
234
|
+
* @returns {{ title:string, readOnlyHint:boolean, destructiveHint:boolean,
|
|
235
|
+
* idempotentHint:boolean, openWorldHint:boolean, domain:string,
|
|
236
|
+
* requiresConfirmation:boolean }}
|
|
237
|
+
*/
|
|
238
|
+
export function buildToolAnnotations(name) {
|
|
239
|
+
const domain = getToolDomain(name);
|
|
240
|
+
const readOnly = isReadOnly(name);
|
|
241
|
+
const destructive = isDestructive(name);
|
|
242
|
+
// Deletes/revokes are retry-safe; purchases and email sends are destructive
|
|
243
|
+
// but NOT idempotent — retrying re-spends money or re-sends the email.
|
|
244
|
+
const nonRetryable = NON_IDEMPOTENT_WRITES.has(name) || /^purchase_|send_email$/.test(name);
|
|
245
|
+
const idempotent = readOnly
|
|
246
|
+
|| IDEMPOTENT_WRITES.has(name)
|
|
247
|
+
|| (destructive && !nonRetryable);
|
|
248
|
+
const openWorld = OPEN_WORLD.has(name);
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
title: titleFor(name),
|
|
252
|
+
readOnlyHint: readOnly,
|
|
253
|
+
destructiveHint: destructive,
|
|
254
|
+
idempotentHint: idempotent,
|
|
255
|
+
openWorldHint: openWorld,
|
|
256
|
+
// Adrata extensions (allowed additional properties on ToolAnnotations).
|
|
257
|
+
domain,
|
|
258
|
+
// Write/destructive tools should be confirmation-gated by the host and are
|
|
259
|
+
// additionally tier-gated + audit-logged server-side.
|
|
260
|
+
requiresConfirmation: !readOnly,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function titleFor(name) {
|
|
265
|
+
return name
|
|
266
|
+
.split('_')
|
|
267
|
+
.map(w => (w ? w[0].toUpperCase() + w.slice(1) : w))
|
|
268
|
+
.join(' ');
|
|
269
|
+
}
|
package/tools/billing.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Billing tools for Adrata MCP Server.
|
|
3
|
+
*
|
|
4
|
+
* Provides two tools:
|
|
5
|
+
* - upgrade_account: Opens browser to Adrata Edition signup page
|
|
6
|
+
* - check_subscription: Returns current plan, usage, and trial status
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { execFile } from 'node:child_process';
|
|
11
|
+
|
|
12
|
+
const SIGNUP_URL = 'https://adrata.com/edition/signup';
|
|
13
|
+
|
|
14
|
+
function openBrowser(url) {
|
|
15
|
+
if (process.platform === 'darwin') execFile('open', [url], () => {});
|
|
16
|
+
else if (process.platform === 'win32') {
|
|
17
|
+
execFile('rundll32.exe', ['url.dll,FileProtocolHandler', url], () => {});
|
|
18
|
+
} else execFile('xdg-open', [url], () => {});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Register billing tools on the MCP server instance.
|
|
23
|
+
*
|
|
24
|
+
* @param {import('@modelcontextprotocol/sdk/server/mcp.js').McpServer} server
|
|
25
|
+
* @param {object} options
|
|
26
|
+
* @param {Function} options.api - HTTP helper for API calls
|
|
27
|
+
* @param {Function} options.ok - Response formatter
|
|
28
|
+
* @param {object} options.auth - Authentication context from authenticate()
|
|
29
|
+
*/
|
|
30
|
+
export function registerBillingTools(server, { api, ok, auth }) {
|
|
31
|
+
// --------------------------------------------------------------------------
|
|
32
|
+
// upgrade_account — opens browser to signup/upgrade page
|
|
33
|
+
// --------------------------------------------------------------------------
|
|
34
|
+
server.tool(
|
|
35
|
+
'upgrade_account',
|
|
36
|
+
'Open the Adrata Edition signup page in your browser to upgrade your account. ' +
|
|
37
|
+
'Free users get a 14-day Pro trial (no credit card required). ' +
|
|
38
|
+
'Pro users can manage their subscription. ' +
|
|
39
|
+
'Enterprise users are directed to schedule a demo.',
|
|
40
|
+
{
|
|
41
|
+
plan: z.enum(['pro', 'enterprise']).optional()
|
|
42
|
+
.describe('Target plan: "pro" for self-serve upgrade, "enterprise" for sales contact. Defaults to "pro".'),
|
|
43
|
+
},
|
|
44
|
+
async (args) => {
|
|
45
|
+
const targetPlan = args.plan || 'pro';
|
|
46
|
+
|
|
47
|
+
if (targetPlan === 'enterprise') {
|
|
48
|
+
return ok({
|
|
49
|
+
action: 'schedule_demo',
|
|
50
|
+
message: 'Enterprise plans require a conversation with our team. Schedule a demo to get started.',
|
|
51
|
+
url: 'https://adrata.com/demo',
|
|
52
|
+
calendar: 'https://cal.com/adrata/enterprise-demo',
|
|
53
|
+
next_steps: [
|
|
54
|
+
'Click the demo link above to schedule a call',
|
|
55
|
+
'Our team will customize a plan for your organization',
|
|
56
|
+
'Enterprise includes SSO, custom integrations, and dedicated support',
|
|
57
|
+
],
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Pro upgrade / signup
|
|
62
|
+
const url = auth.authenticated
|
|
63
|
+
? `${SIGNUP_URL}?upgrade=true`
|
|
64
|
+
: SIGNUP_URL;
|
|
65
|
+
|
|
66
|
+
// Attempt to open browser
|
|
67
|
+
let browserOpened = false;
|
|
68
|
+
try {
|
|
69
|
+
openBrowser(url);
|
|
70
|
+
browserOpened = true;
|
|
71
|
+
} catch {
|
|
72
|
+
browserOpened = false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return ok({
|
|
76
|
+
action: 'upgrade_to_pro',
|
|
77
|
+
url,
|
|
78
|
+
browser_opened: browserOpened,
|
|
79
|
+
message: browserOpened
|
|
80
|
+
? 'Opening signup page in your browser...'
|
|
81
|
+
: `Open this URL to sign up: ${url}`,
|
|
82
|
+
plan: {
|
|
83
|
+
name: 'Adrata Pro',
|
|
84
|
+
price: '$2,000/seat/year',
|
|
85
|
+
trial: '14-day free trial, no credit card required',
|
|
86
|
+
features: [
|
|
87
|
+
'Full company and contact intelligence',
|
|
88
|
+
'Buying intent signals and deal authority mapping',
|
|
89
|
+
'Pipeline analytics and revenue forecasting',
|
|
90
|
+
'Competitive intelligence briefs',
|
|
91
|
+
'Priority Pursuits ranked daily action lists',
|
|
92
|
+
'Meeting summaries and action items',
|
|
93
|
+
'AI-powered enrichment and scoring',
|
|
94
|
+
],
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
// --------------------------------------------------------------------------
|
|
101
|
+
// check_subscription — returns current plan, usage, and trial status
|
|
102
|
+
// --------------------------------------------------------------------------
|
|
103
|
+
server.tool(
|
|
104
|
+
'check_subscription',
|
|
105
|
+
'Check your current Adrata subscription plan, usage limits, trial status, and billing details. ' +
|
|
106
|
+
'Works at all tiers: free users see upgrade options, pro users see usage and trial countdown, ' +
|
|
107
|
+
'enterprise users see full workspace subscription details.',
|
|
108
|
+
{},
|
|
109
|
+
async () => {
|
|
110
|
+
// Free tier — no API call possible
|
|
111
|
+
if (!auth.authenticated) {
|
|
112
|
+
return ok({
|
|
113
|
+
plan: 'free',
|
|
114
|
+
status: 'active',
|
|
115
|
+
usage: {
|
|
116
|
+
tools_available: 'Search and email tools only',
|
|
117
|
+
tools_used_today: 'N/A (no tracking in free tier)',
|
|
118
|
+
},
|
|
119
|
+
upgrade: {
|
|
120
|
+
message: 'Upgrade to Pro for full intelligence and analytics.',
|
|
121
|
+
url: SIGNUP_URL,
|
|
122
|
+
trial: '14-day free trial, no credit card required',
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Pro or Enterprise — fetch subscription from API
|
|
128
|
+
try {
|
|
129
|
+
const data = await api('GET', '/api/v1/mcp/subscription');
|
|
130
|
+
return ok({
|
|
131
|
+
plan: data.plan || auth.tier,
|
|
132
|
+
status: data.status || 'active',
|
|
133
|
+
trial: data.trial || null,
|
|
134
|
+
usage: data.usage || null,
|
|
135
|
+
billing: data.billing || null,
|
|
136
|
+
manage_url: data.manage_url || null,
|
|
137
|
+
});
|
|
138
|
+
} catch (err) {
|
|
139
|
+
// Fallback if endpoint not available yet
|
|
140
|
+
return ok({
|
|
141
|
+
plan: auth.tier,
|
|
142
|
+
status: 'active',
|
|
143
|
+
message: 'Subscription details are available in your Adrata dashboard.',
|
|
144
|
+
dashboard_url: 'https://app.adrata.com/settings/billing',
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
);
|
|
149
|
+
}
|