@dropspot/mcp 1.0.0 → 1.3.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/LICENSE +21 -0
- package/README.md +46 -9
- package/dist/index.d.ts +2 -0
- package/dist/index.js +264 -15
- package/glama.json +9 -0
- package/package.json +53 -46
- package/smithery.yaml +27 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Drop Spot Technologies
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -59,21 +59,55 @@ Add to `.cursor/mcp.json` in your project or global settings:
|
|
|
59
59
|
}
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
#### Option C:
|
|
63
|
-
|
|
62
|
+
#### Option C: Claude Code (CLI)
|
|
63
|
+
Add Drop Spot to Claude Code:
|
|
64
|
+
|
|
64
65
|
```bash
|
|
65
|
-
npx -y @
|
|
66
|
+
claude mcp add dropspot npx -y @dropspot/mcp --env DROPSPOT_API_KEY=ds_live_YOUR_ACTUAL_KEY_HERE DROPSPOT_API_BASE_URL=https://godropspot.com/api/v1
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
#### Option D: Windsurf / VS Code / Antigravity
|
|
70
|
+
Add to your client's MCP configuration (`mcpServers`):
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"mcpServers": {
|
|
75
|
+
"dropspot": {
|
|
76
|
+
"command": "npx",
|
|
77
|
+
"args": ["-y", "@dropspot/mcp"],
|
|
78
|
+
"env": {
|
|
79
|
+
"DROPSPOT_API_KEY": "ds_live_YOUR_ACTUAL_KEY_HERE",
|
|
80
|
+
"DROPSPOT_API_BASE_URL": "https://godropspot.com/api/v1"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
66
85
|
```
|
|
67
86
|
|
|
68
87
|
---
|
|
69
88
|
|
|
89
|
+
## 🌐 Public Registries & Discovery
|
|
90
|
+
|
|
91
|
+
Drop Spot is an open, unproxied MCP server available across major AI registries:
|
|
92
|
+
|
|
93
|
+
- **Smithery.ai:** Direct registry listing indexed via `smithery.yaml` (Arcade.dev-powered, zero proxy latency).
|
|
94
|
+
- **Glama.ai:** Verified MCP listing claimed via `glama.json` ([glama.ai/mcp/servers](https://glama.ai/mcp/servers)).
|
|
95
|
+
- **PulseMCP:** Listed in the community catalog ([pulsemcp.com](https://pulsemcp.com)).
|
|
96
|
+
- **Official Model Context Protocol:** Cataloged on [modelcontextprotocol/servers](https://github.com/modelcontextprotocol/servers).
|
|
97
|
+
- **npm:** Zero-install direct execution via `npx -y @dropspot/mcp`.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
70
101
|
## 💬 Prompts Your AI Understands
|
|
71
102
|
|
|
72
103
|
Once connected, your AI gains native understanding of your Drop Spot workspace:
|
|
73
104
|
|
|
74
105
|
- *"Create an intake request for Sarah Jenkins using our 2026 Tax Return template."*
|
|
75
106
|
- *"Show me our client list and search for Acme Corp."*
|
|
76
|
-
- *"
|
|
107
|
+
- *"Get the client CSV template and mold this spreadsheet data into Drop Spot format."*
|
|
108
|
+
- *"Import this CSV of 25 clients from TaxDome into our directory."*
|
|
109
|
+
- *"Export our entire client roster to a CSV file."*
|
|
110
|
+
- *"Update Sarah's phone number to (123) 456-7890 and add a note that she is a VIP client."*
|
|
77
111
|
- *"Check if Sarah uploaded her W-2 form yet."*
|
|
78
112
|
- *"Review Sarah's uploaded W-2 and approve it."*
|
|
79
113
|
- *"Reject item #2 with the note: 'Page 2 is blurry. Please re-upload a clear scan.' "*
|
|
@@ -82,7 +116,7 @@ Once connected, your AI gains native understanding of your Drop Spot workspace:
|
|
|
82
116
|
|
|
83
117
|
---
|
|
84
118
|
|
|
85
|
-
## 🛠️ Available MCP Tools (
|
|
119
|
+
## 🛠️ Available MCP Tools (15 Tools)
|
|
86
120
|
|
|
87
121
|
| Tool Name | Description |
|
|
88
122
|
| :--- | :--- |
|
|
@@ -91,9 +125,12 @@ Once connected, your AI gains native understanding of your Drop Spot workspace:
|
|
|
91
125
|
| `get_intake_request` | Retrieve complete details of a specific request, including each checklist item, upload statuses, and file metadata. |
|
|
92
126
|
| `review_item` | Review an uploaded file: approve it or reject it with custom feedback to prompt the client for a re-upload. |
|
|
93
127
|
| `get_file_download_link` | Generate a short-lived (5-minute) secure presigned URL to inspect or download an uploaded client file. |
|
|
94
|
-
| `list_clients` | Search and browse your firm's client directory by name, email, or
|
|
95
|
-
| `get_client` | Fetch a client record with
|
|
96
|
-
| `create_or_update_client` | Add a new client or update
|
|
128
|
+
| `list_clients` | Search and browse your firm's client directory by name, email, company, entity type, status, or tag. |
|
|
129
|
+
| `get_client` | Fetch a client record with full accounting CRM metadata, spouses/linked contacts, tags, and intake history. |
|
|
130
|
+
| `create_or_update_client` | Add a new client or update contact & CRM profile (tax entity, FYE, cadence, state, tags, masked ID, pinned notes, linked contacts). |
|
|
131
|
+
| `get_clients_csv_template` | Inspect the official CSV template, header specifications, and format guidelines so AI can mold arbitrary user spreadsheets into clean Drop Spot format. |
|
|
132
|
+
| `import_clients_csv` | Batch import client rosters from raw CSV text (with 50+ synonym headers & cell heuristics) or structured arrays. Deduplicates and merges profiles by email. |
|
|
133
|
+
| `export_clients_csv` | Export all client profiles as an RFC 4180 compliant CSV string with entity types, filing cadences, and formula injection defenses. |
|
|
97
134
|
| `list_templates` | View your reusable checklist templates (e.g. 1040 Tax Return, KYC, Mortgage Intake). |
|
|
98
135
|
| `get_template` | Inspect a specific checklist template and its default items. |
|
|
99
136
|
| `create_template` | Create a new reusable checklist template with predefined items and categories. |
|
|
@@ -106,7 +143,7 @@ Once connected, your AI gains native understanding of your Drop Spot workspace:
|
|
|
106
143
|
- **Zero AI Training:** Client documents and personal data are **never** used to train public or proprietary AI models.
|
|
107
144
|
- **Short-Lived Signed URLs:** File downloads use ephemeral 5-minute pre-signed URLs; file binaries are never permanently exposed over the wire.
|
|
108
145
|
- **Scoped API Tokens:** Generate API keys restricted strictly to specific operations (`requests:read`, `requests:write`, `items:review`, `clients:write`, etc.).
|
|
109
|
-
- **Human-in-the-Loop:** AI tools execute actions on your behalf with
|
|
146
|
+
- **Human-in-the-Loop:** AI tools execute actions on your behalf with scoped permissions, clear item status tracking, and 1-click token revocation.
|
|
110
147
|
|
|
111
148
|
---
|
|
112
149
|
|
package/dist/index.d.ts
ADDED
package/dist/index.js
CHANGED
|
@@ -24,7 +24,7 @@ async function apiRequest(endpoint, options = {}) {
|
|
|
24
24
|
}
|
|
25
25
|
const server = new Server({
|
|
26
26
|
name: 'dropspot-mcp',
|
|
27
|
-
version: '1.
|
|
27
|
+
version: '1.3.0',
|
|
28
28
|
}, {
|
|
29
29
|
capabilities: {
|
|
30
30
|
tools: {},
|
|
@@ -166,7 +166,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
166
166
|
// CLIENTS MANAGEMENT TOOLS
|
|
167
167
|
{
|
|
168
168
|
name: 'list_clients',
|
|
169
|
-
description: 'List and search clients in the Drop Spot directory. Filter by name, email, or
|
|
169
|
+
description: 'List and search clients in the Drop Spot directory. Filter by name, email, company, entity type, status, or tag.',
|
|
170
170
|
inputSchema: {
|
|
171
171
|
type: 'object',
|
|
172
172
|
properties: {
|
|
@@ -174,6 +174,20 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
174
174
|
type: 'string',
|
|
175
175
|
description: 'Search string to filter clients by name, email, or company name',
|
|
176
176
|
},
|
|
177
|
+
entityType: {
|
|
178
|
+
type: 'string',
|
|
179
|
+
enum: ['individual', 's_corp', 'c_corp', 'partnership', 'llc', 'non_profit', 'trust_estate'],
|
|
180
|
+
description: 'Filter by tax entity classification',
|
|
181
|
+
},
|
|
182
|
+
status: {
|
|
183
|
+
type: 'string',
|
|
184
|
+
enum: ['active', 'lead', 'archived'],
|
|
185
|
+
description: 'Filter by client account status',
|
|
186
|
+
},
|
|
187
|
+
tag: {
|
|
188
|
+
type: 'string',
|
|
189
|
+
description: 'Filter by specific tag (e.g. "QBO", "Extension Needed")',
|
|
190
|
+
},
|
|
177
191
|
limit: {
|
|
178
192
|
type: 'number',
|
|
179
193
|
description: 'Max number of clients to return (default: 50, max: 100)',
|
|
@@ -183,7 +197,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
183
197
|
},
|
|
184
198
|
{
|
|
185
199
|
name: 'get_client',
|
|
186
|
-
description: 'Retrieve detailed profile information for a specific client, including
|
|
200
|
+
description: 'Retrieve detailed profile and CRM information for a specific client, including tax entity metadata, spouses/linked contacts, tags, pinned accountant note, and active/completed document requests.',
|
|
187
201
|
inputSchema: {
|
|
188
202
|
type: 'object',
|
|
189
203
|
properties: {
|
|
@@ -197,13 +211,13 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
197
211
|
},
|
|
198
212
|
{
|
|
199
213
|
name: 'create_or_update_client',
|
|
200
|
-
description: 'Add a new client to the directory or update an existing client
|
|
214
|
+
description: 'Add a new client to the directory or update an existing client with accounting CRM metadata (entity type, filing cadence, FYE, state, tags, masked tax ID, pinned accountant notes, and linked contacts).',
|
|
201
215
|
inputSchema: {
|
|
202
216
|
type: 'object',
|
|
203
217
|
properties: {
|
|
204
218
|
name: {
|
|
205
219
|
type: 'string',
|
|
206
|
-
description: 'Full name of the client',
|
|
220
|
+
description: 'Full name of the client (e.g. "Jane Doe")',
|
|
207
221
|
},
|
|
208
222
|
email: {
|
|
209
223
|
type: 'string',
|
|
@@ -215,16 +229,147 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
215
229
|
},
|
|
216
230
|
company: {
|
|
217
231
|
type: 'string',
|
|
218
|
-
description: 'Company or business name',
|
|
232
|
+
description: 'Company or business entity name',
|
|
219
233
|
},
|
|
220
234
|
notes: {
|
|
221
235
|
type: 'string',
|
|
222
|
-
description: '
|
|
236
|
+
description: 'General internal notes about this client',
|
|
237
|
+
},
|
|
238
|
+
entityType: {
|
|
239
|
+
type: 'string',
|
|
240
|
+
enum: ['individual', 's_corp', 'c_corp', 'partnership', 'llc', 'non_profit', 'trust_estate'],
|
|
241
|
+
description: 'Tax entity classification (e.g. "individual" for 1040, "s_corp" for 1120-S, "c_corp" for 1120, "partnership" for 1065)',
|
|
242
|
+
},
|
|
243
|
+
status: {
|
|
244
|
+
type: 'string',
|
|
245
|
+
enum: ['active', 'lead', 'archived'],
|
|
246
|
+
description: 'Account status (defaults to "active")',
|
|
247
|
+
},
|
|
248
|
+
fiscalYearEnd: {
|
|
249
|
+
type: 'string',
|
|
250
|
+
description: 'Fiscal Year End month/day (e.g. "12/31", "06/30")',
|
|
251
|
+
},
|
|
252
|
+
filingCadence: {
|
|
253
|
+
type: 'string',
|
|
254
|
+
enum: ['annual', 'quarterly', 'monthly'],
|
|
255
|
+
description: 'Tax filing frequency',
|
|
256
|
+
},
|
|
257
|
+
stateOfFiling: {
|
|
258
|
+
type: 'string',
|
|
259
|
+
description: 'US State abbreviation for tax filing (e.g. "FL", "CA", "NY")',
|
|
260
|
+
},
|
|
261
|
+
taxYear: {
|
|
262
|
+
type: 'string',
|
|
263
|
+
description: 'Current filing tax year (e.g. "2026")',
|
|
264
|
+
},
|
|
265
|
+
tags: {
|
|
266
|
+
type: 'array',
|
|
267
|
+
items: { type: 'string' },
|
|
268
|
+
description: 'Accounting tags (e.g. ["QBO", "Extension Needed", "VIP", "Monthly Books"])',
|
|
269
|
+
},
|
|
270
|
+
pinnedNote: {
|
|
271
|
+
type: 'string',
|
|
272
|
+
description: 'Sticky internal accountant note (communication quirks, deadline habits)',
|
|
273
|
+
},
|
|
274
|
+
qboId: {
|
|
275
|
+
type: 'string',
|
|
276
|
+
description: 'QuickBooks Online or Xero accounting customer ID',
|
|
277
|
+
},
|
|
278
|
+
taxSoftwareId: {
|
|
279
|
+
type: 'string',
|
|
280
|
+
description: 'Drake, UltraTax, or CCH Axcess client ID',
|
|
281
|
+
},
|
|
282
|
+
maskedId: {
|
|
283
|
+
type: 'string',
|
|
284
|
+
description: 'Masked tax ID / SSN / EIN (last 4 digits only, e.g. "1234" or "***-**-1234")',
|
|
285
|
+
},
|
|
286
|
+
linkedContacts: {
|
|
287
|
+
type: 'array',
|
|
288
|
+
items: {
|
|
289
|
+
type: 'object',
|
|
290
|
+
properties: {
|
|
291
|
+
name: { type: 'string', description: 'Full name of contact' },
|
|
292
|
+
role: { type: 'string', description: 'Role (e.g. "Spouse", "Bookkeeper", "Owner")' },
|
|
293
|
+
email: { type: 'string', description: 'Contact email' },
|
|
294
|
+
phone: { type: 'string', description: 'Contact phone' },
|
|
295
|
+
},
|
|
296
|
+
required: ['name', 'role'],
|
|
297
|
+
},
|
|
298
|
+
description: 'Associated contacts, spouses, bookkeepers, or family members',
|
|
223
299
|
},
|
|
224
300
|
},
|
|
225
301
|
required: ['name', 'email'],
|
|
226
302
|
},
|
|
227
303
|
},
|
|
304
|
+
{
|
|
305
|
+
name: 'get_clients_csv_template',
|
|
306
|
+
description: 'Retrieve the official Drop Spot CSV template, column specifications, and sample rows for client rosters. AI models can use this schema to mold, map, or normalize arbitrary user spreadsheets into the exact Drop Spot format before importing.',
|
|
307
|
+
inputSchema: {
|
|
308
|
+
type: 'object',
|
|
309
|
+
properties: {
|
|
310
|
+
includeSampleRows: {
|
|
311
|
+
type: 'boolean',
|
|
312
|
+
description: 'Whether to include sample client rows in the template (default: true)',
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
name: 'import_clients_csv',
|
|
319
|
+
description: 'Batch import a client roster into the workspace directory. Accepts raw CSV text (with intelligent auto-mapping across 50+ synonym headers like TaxDome, Drake, QuickBooks, UltraTax, etc.) or an array of client objects. Automatically deduplicates and merges existing profiles by email.',
|
|
320
|
+
inputSchema: {
|
|
321
|
+
type: 'object',
|
|
322
|
+
properties: {
|
|
323
|
+
csvText: {
|
|
324
|
+
type: 'string',
|
|
325
|
+
description: 'Raw CSV text containing client rows to import',
|
|
326
|
+
},
|
|
327
|
+
clients: {
|
|
328
|
+
type: 'array',
|
|
329
|
+
items: {
|
|
330
|
+
type: 'object',
|
|
331
|
+
properties: {
|
|
332
|
+
name: { type: 'string', description: 'Full name of client' },
|
|
333
|
+
email: { type: 'string', description: 'Client email address' },
|
|
334
|
+
phone: { type: 'string', description: 'Client phone number' },
|
|
335
|
+
company: { type: 'string', description: 'Company or business entity name' },
|
|
336
|
+
entityType: { type: 'string', description: 'Tax entity type (e.g. "individual", "s_corp", "c_corp", "partnership", "llc")' },
|
|
337
|
+
status: { type: 'string', description: 'Lifecycle status ("active", "extension", "lead", "inactive")' },
|
|
338
|
+
maskedId: { type: 'string', description: 'SSN/EIN masked tax ID (e.g. "***-**-1234")' },
|
|
339
|
+
stateOfFiling: { type: 'string', description: 'Filing state (e.g. "FL", "NY")' },
|
|
340
|
+
taxYear: { type: 'string', description: 'Tax year (e.g. "2026")' },
|
|
341
|
+
tags: { type: 'array', items: { type: 'string' }, description: 'Tags' },
|
|
342
|
+
pinnedNote: { type: 'string', description: 'Internal pinned notes' },
|
|
343
|
+
notes: { type: 'string', description: 'General client notes' },
|
|
344
|
+
},
|
|
345
|
+
required: ['name', 'email'],
|
|
346
|
+
},
|
|
347
|
+
description: 'Alternative structured array of client objects if already transformed by AI',
|
|
348
|
+
},
|
|
349
|
+
columnOverrides: {
|
|
350
|
+
type: 'object',
|
|
351
|
+
description: 'Optional mapping of standard fields to custom header names in the CSV',
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
name: 'export_clients_csv',
|
|
358
|
+
description: 'Export all client profiles from the workspace directory as an RFC 4180 compliant CSV string, complete with tax entities, filing cadences, and tags.',
|
|
359
|
+
inputSchema: {
|
|
360
|
+
type: 'object',
|
|
361
|
+
properties: {
|
|
362
|
+
tag: {
|
|
363
|
+
type: 'string',
|
|
364
|
+
description: 'Optional filter by client tag (e.g. "VIP", "1040")',
|
|
365
|
+
},
|
|
366
|
+
status: {
|
|
367
|
+
type: 'string',
|
|
368
|
+
description: 'Optional filter by status (e.g. "active", "extension", "lead", "inactive")',
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
},
|
|
228
373
|
// TEMPLATES MANAGEMENT TOOLS
|
|
229
374
|
{
|
|
230
375
|
name: 'list_templates',
|
|
@@ -479,21 +624,31 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
479
624
|
case 'list_clients': {
|
|
480
625
|
const params = new URLSearchParams();
|
|
481
626
|
if (args?.search)
|
|
482
|
-
params.set('search', String(args
|
|
627
|
+
params.set('search', String(args?.search));
|
|
483
628
|
if (args?.limit)
|
|
484
|
-
params.set('limit', String(args
|
|
629
|
+
params.set('limit', String(args?.limit));
|
|
630
|
+
if (args?.entityType)
|
|
631
|
+
params.set('entityType', String(args?.entityType));
|
|
632
|
+
if (args?.status)
|
|
633
|
+
params.set('status', String(args?.status));
|
|
485
634
|
const res = await apiRequest(`/clients?${params.toString()}`);
|
|
486
|
-
|
|
635
|
+
let clients = res.data || [];
|
|
636
|
+
if (args?.tag) {
|
|
637
|
+
const searchTag = String(args.tag).toLowerCase();
|
|
638
|
+
clients = clients.filter((c) => Array.isArray(c.tags) && c.tags.some((t) => t.toLowerCase() === searchTag));
|
|
639
|
+
}
|
|
487
640
|
if (clients.length === 0) {
|
|
488
641
|
return {
|
|
489
|
-
content: [{ type: 'text', text: 'No clients found
|
|
642
|
+
content: [{ type: 'text', text: 'No clients found in the directory.' }],
|
|
490
643
|
};
|
|
491
644
|
}
|
|
492
645
|
const formatted = clients
|
|
493
646
|
.map((c) => {
|
|
494
|
-
const company = c.company ? `
|
|
647
|
+
const company = c.company ? ` (${c.company})` : '';
|
|
495
648
|
const phone = c.phone ? ` | Phone: ${c.phone}` : '';
|
|
496
|
-
|
|
649
|
+
const entity = c.entityType ? ` | Entity: ${c.entityType}` : '';
|
|
650
|
+
const tags = c.tags?.length ? ` | Tags: [${c.tags.join(', ')}]` : '';
|
|
651
|
+
return `• ${c.name} <${c.email}>${company}${phone}${entity}${tags}\n ID: ${c.id}`;
|
|
497
652
|
})
|
|
498
653
|
.join('\n\n');
|
|
499
654
|
return {
|
|
@@ -515,12 +670,28 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
515
670
|
.map((r) => ` - [${r.status.toUpperCase()}] ${r.title} (ID: ${r.id})`)
|
|
516
671
|
.join('\n');
|
|
517
672
|
}
|
|
673
|
+
let contactsSummary = 'No linked contacts.';
|
|
674
|
+
if (c.linkedContacts && c.linkedContacts.length > 0) {
|
|
675
|
+
contactsSummary = c.linkedContacts
|
|
676
|
+
.map((lc) => ` - ${lc.name} (${lc.role}) ${lc.email ? `<${lc.email}>` : ''}`)
|
|
677
|
+
.join('\n');
|
|
678
|
+
}
|
|
518
679
|
const report = `👤 Client Profile: ${c.name}\n` +
|
|
519
680
|
`• ID: ${c.id}\n` +
|
|
520
681
|
`• Email: ${c.email}\n` +
|
|
521
682
|
`• Phone: ${c.phone || 'Not provided'}\n` +
|
|
522
683
|
`• Company: ${c.company || 'Not provided'}\n` +
|
|
684
|
+
`• Entity Type: ${c.entityType || 'individual'}\n` +
|
|
685
|
+
`• Status: ${c.status || 'active'}\n` +
|
|
686
|
+
`• Fiscal Year End: ${c.fiscalYearEnd || '12/31'}\n` +
|
|
687
|
+
`• Filing Cadence: ${c.filingCadence || 'annual'}\n` +
|
|
688
|
+
`• State: ${c.stateOfFiling || 'N/A'}\n` +
|
|
689
|
+
`• Tax Year: ${c.taxYear || '2026'}\n` +
|
|
690
|
+
`• Masked Tax ID: ${c.maskedId || 'None'}\n` +
|
|
691
|
+
`• Tags: ${c.tags?.length ? `[${c.tags.join(', ')}]` : 'None'}\n` +
|
|
692
|
+
`• Pinned Note: ${c.pinnedNote ? `"${c.pinnedNote}"` : 'None'}\n` +
|
|
523
693
|
`• Notes: ${c.notes || 'None'}\n\n` +
|
|
694
|
+
`Linked Contacts & Family:\n${contactsSummary}\n\n` +
|
|
524
695
|
`Document Intake Requests:\n${requestsSummary}`;
|
|
525
696
|
return {
|
|
526
697
|
content: [{ type: 'text', text: report }],
|
|
@@ -533,6 +704,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
533
704
|
phone: args?.phone,
|
|
534
705
|
company: args?.company,
|
|
535
706
|
notes: args?.notes,
|
|
707
|
+
entityType: args?.entityType,
|
|
708
|
+
status: args?.status,
|
|
709
|
+
fiscalYearEnd: args?.fiscalYearEnd,
|
|
710
|
+
filingCadence: args?.filingCadence,
|
|
711
|
+
stateOfFiling: args?.stateOfFiling,
|
|
712
|
+
taxYear: args?.taxYear,
|
|
713
|
+
tags: args?.tags,
|
|
714
|
+
pinnedNote: args?.pinnedNote,
|
|
715
|
+
qboId: args?.qboId,
|
|
716
|
+
taxSoftwareId: args?.taxSoftwareId,
|
|
717
|
+
maskedId: args?.maskedId,
|
|
718
|
+
linkedContacts: args?.linkedContacts,
|
|
536
719
|
};
|
|
537
720
|
const res = await apiRequest('/clients', {
|
|
538
721
|
method: 'POST',
|
|
@@ -548,9 +731,75 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
548
731
|
`• ID: ${c.id}\n` +
|
|
549
732
|
`• Name: ${c.name}\n` +
|
|
550
733
|
`• Email: ${c.email}\n` +
|
|
551
|
-
`• Phone: ${c.phone || 'N/A'}\n` +
|
|
552
734
|
`• Company: ${c.company || 'N/A'}\n` +
|
|
553
|
-
`•
|
|
735
|
+
`• Entity: ${c.entityType || 'individual'}\n` +
|
|
736
|
+
`• Status: ${c.status || 'active'}\n` +
|
|
737
|
+
`• Tags: ${c.tags?.length ? `[${c.tags.join(', ')}]` : 'None'}\n` +
|
|
738
|
+
`• FYE: ${c.fiscalYearEnd || '12/31'}\n` +
|
|
739
|
+
`• Pinned Note: ${c.pinnedNote ? `"${c.pinnedNote}"` : 'None'}`,
|
|
740
|
+
},
|
|
741
|
+
],
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
case 'get_clients_csv_template': {
|
|
745
|
+
const res = await apiRequest('/clients/template');
|
|
746
|
+
return {
|
|
747
|
+
content: [
|
|
748
|
+
{
|
|
749
|
+
type: 'text',
|
|
750
|
+
text: `📋 Drop Spot Client CSV Template Specification:\n\n` +
|
|
751
|
+
`\`\`\`csv\n${res.templateCsv}\n\`\`\`\n\n` +
|
|
752
|
+
`Key Field Guidelines for AI Data Molding:\n` +
|
|
753
|
+
`• Email is required for every client profile.\n` +
|
|
754
|
+
`• Standard placeholder phone: (123)456-7890\n` +
|
|
755
|
+
`• Masked IDs strictly show last 4 digits (***-**-XXXX or **-***XXXX)\n` +
|
|
756
|
+
`• Entity types: individual, s_corp, c_corp, partnership, llc\n\n` +
|
|
757
|
+
`AI models can mold arbitrary spreadsheet rows into this format and pass them directly to import_clients_csv.`,
|
|
758
|
+
},
|
|
759
|
+
],
|
|
760
|
+
};
|
|
761
|
+
}
|
|
762
|
+
case 'import_clients_csv': {
|
|
763
|
+
const payload = {};
|
|
764
|
+
if (args?.csvText)
|
|
765
|
+
payload.csv = args.csvText;
|
|
766
|
+
if (args?.clients)
|
|
767
|
+
payload.clients = args.clients;
|
|
768
|
+
if (args?.columnOverrides)
|
|
769
|
+
payload.columnOverrides = args.columnOverrides;
|
|
770
|
+
const res = await apiRequest('/clients/import', {
|
|
771
|
+
method: 'POST',
|
|
772
|
+
body: JSON.stringify(payload),
|
|
773
|
+
});
|
|
774
|
+
const previewList = (res.clients || [])
|
|
775
|
+
.slice(0, 5)
|
|
776
|
+
.map((c) => `• ${c.name} (${c.email}) - ${c.entity_type || 'individual'}`)
|
|
777
|
+
.join('\n');
|
|
778
|
+
return {
|
|
779
|
+
content: [
|
|
780
|
+
{
|
|
781
|
+
type: 'text',
|
|
782
|
+
text: `✅ Successfully imported ${res.imported || 0} client profile(s) into Drop Spot workspace!\n\n` +
|
|
783
|
+
(previewList ? `Preview of imported clients:\n${previewList}\n\n` : '') +
|
|
784
|
+
`Clients are now in the directory and ready for 1-click document requests.`,
|
|
785
|
+
},
|
|
786
|
+
],
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
case 'export_clients_csv': {
|
|
790
|
+
const params = new URLSearchParams();
|
|
791
|
+
params.set('format', 'json');
|
|
792
|
+
if (args?.tag)
|
|
793
|
+
params.set('tag', String(args.tag));
|
|
794
|
+
if (args?.status)
|
|
795
|
+
params.set('status', String(args.status));
|
|
796
|
+
const res = await apiRequest(`/clients/export?${params.toString()}`);
|
|
797
|
+
return {
|
|
798
|
+
content: [
|
|
799
|
+
{
|
|
800
|
+
type: 'text',
|
|
801
|
+
text: `📁 Exported ${res.count || 0} client profile(s) as RFC 4180 CSV:\n\n` +
|
|
802
|
+
`\`\`\`csv\n${res.csv}\n\`\`\``,
|
|
554
803
|
},
|
|
555
804
|
],
|
|
556
805
|
};
|
package/glama.json
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://glama.ai/mcp/schemas/server.json",
|
|
3
|
+
"name": "@dropspot/mcp",
|
|
4
|
+
"description": "Model Context Protocol (MCP) server for Drop Spot — automated client document collection, file intake, checklist management, and 1-click reviews.",
|
|
5
|
+
"maintainers": [
|
|
6
|
+
"officialdropspot",
|
|
7
|
+
"leoalfonso14"
|
|
8
|
+
]
|
|
9
|
+
}
|
package/package.json
CHANGED
|
@@ -1,46 +1,53 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@dropspot/mcp",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Model Context Protocol (MCP) server for Drop Spot — automated client document collection, file intake, checklist management, and 1-click reviews for Claude Desktop, Cursor, and AI agents.",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"homepage": "https://godropspot.com",
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@dropspot/mcp",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "Model Context Protocol (MCP) server for Drop Spot — automated client document collection, file intake, checklist management, and 1-click reviews for Claude Desktop, Cursor, and AI agents.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"homepage": "https://godropspot.com",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/officialdropspot/dropspot-mcp.git"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"mcp",
|
|
13
|
+
"model-context-protocol",
|
|
14
|
+
"claude-desktop",
|
|
15
|
+
"cursor",
|
|
16
|
+
"antigravity",
|
|
17
|
+
"file-sharing",
|
|
18
|
+
"document-collection",
|
|
19
|
+
"client-portal",
|
|
20
|
+
"client-intake",
|
|
21
|
+
"tax-documents",
|
|
22
|
+
"paperwork-automation",
|
|
23
|
+
"file-intake"
|
|
24
|
+
],
|
|
25
|
+
"main": "dist/index.js",
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"README.md",
|
|
29
|
+
"LICENSE",
|
|
30
|
+
"smithery.yaml",
|
|
31
|
+
"glama.json"
|
|
32
|
+
],
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"bin": {
|
|
38
|
+
"dropspot-mcp": "dist/index.js"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "tsc",
|
|
42
|
+
"start": "node dist/index.js",
|
|
43
|
+
"prepublishOnly": "npm run build"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@modelcontextprotocol/sdk": "^1.6.1",
|
|
47
|
+
"zod": "^3.24.2"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "^22.10.1",
|
|
51
|
+
"typescript": "~5.7.2"
|
|
52
|
+
}
|
|
53
|
+
}
|
package/smithery.yaml
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Smithery configuration file: https://smithery.ai/docs/config
|
|
2
|
+
startCommand:
|
|
3
|
+
type: stdio
|
|
4
|
+
configSchema:
|
|
5
|
+
type: object
|
|
6
|
+
required:
|
|
7
|
+
- dropspotApiKey
|
|
8
|
+
properties:
|
|
9
|
+
dropspotApiKey:
|
|
10
|
+
type: string
|
|
11
|
+
description: "Your Drop Spot API key (format: ds_live_... or ds_test_...)"
|
|
12
|
+
baseUrl:
|
|
13
|
+
type: string
|
|
14
|
+
description: "Drop Spot API base URL"
|
|
15
|
+
default: "https://portal.godropspot.com"
|
|
16
|
+
commandFunction: |
|
|
17
|
+
(config) => ({
|
|
18
|
+
command: 'npx',
|
|
19
|
+
args: ['-y', '@dropspot/mcp'],
|
|
20
|
+
env: {
|
|
21
|
+
DROPSPOT_API_KEY: config.dropspotApiKey,
|
|
22
|
+
DROPSPOT_API_BASE_URL: config.baseUrl || 'https://portal.godropspot.com'
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
exampleConfig:
|
|
26
|
+
dropspotApiKey: "ds_live_abcdef1234567890"
|
|
27
|
+
baseUrl: "https://portal.godropspot.com"
|