@dropspot/mcp 1.0.0 → 1.2.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 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,14 +59,45 @@ Add to `.cursor/mcp.json` in your project or global settings:
59
59
  }
60
60
  ```
61
61
 
62
- #### Option C: Smithery CLI
63
- Install automatically into Claude Desktop with one command:
62
+ #### Option C: Claude Code (CLI)
63
+ Add Drop Spot to Claude Code:
64
+
64
65
  ```bash
65
- npx -y @smithery/cli install @dropspot/mcp --client claude
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:
@@ -91,9 +122,9 @@ Once connected, your AI gains native understanding of your Drop Spot workspace:
91
122
  | `get_intake_request` | Retrieve complete details of a specific request, including each checklist item, upload statuses, and file metadata. |
92
123
  | `review_item` | Review an uploaded file: approve it or reject it with custom feedback to prompt the client for a re-upload. |
93
124
  | `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 company. |
95
- | `get_client` | Fetch a client record with their full intake history and metadata. |
96
- | `create_or_update_client` | Add a new client or update existing contact details (phone, company, notes). |
125
+ | `list_clients` | Search and browse your firm's client directory by name, email, company, entity type, status, or tag. |
126
+ | `get_client` | Fetch a client record with full accounting CRM metadata, spouses/linked contacts, tags, and intake history. |
127
+ | `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). |
97
128
  | `list_templates` | View your reusable checklist templates (e.g. 1040 Tax Return, KYC, Mortgage Intake). |
98
129
  | `get_template` | Inspect a specific checklist template and its default items. |
99
130
  | `create_template` | Create a new reusable checklist template with predefined items and categories. |
@@ -106,7 +137,7 @@ Once connected, your AI gains native understanding of your Drop Spot workspace:
106
137
  - **Zero AI Training:** Client documents and personal data are **never** used to train public or proprietary AI models.
107
138
  - **Short-Lived Signed URLs:** File downloads use ephemeral 5-minute pre-signed URLs; file binaries are never permanently exposed over the wire.
108
139
  - **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 complete audit trails. You retain full oversight with real-time logs and 1-click token revocation.
140
+ - **Human-in-the-Loop:** AI tools execute actions on your behalf with scoped permissions, clear item status tracking, and 1-click token revocation.
110
141
 
111
142
  ---
112
143
 
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
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.1.0',
27
+ version: '1.2.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 company.',
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 their active and historical document requests.',
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’s contact details, phone, company, or notes.',
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,11 +229,73 @@ 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: 'Internal notes about this client',
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'],
@@ -479,21 +555,31 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
479
555
  case 'list_clients': {
480
556
  const params = new URLSearchParams();
481
557
  if (args?.search)
482
- params.set('search', String(args.search));
558
+ params.set('search', String(args?.search));
483
559
  if (args?.limit)
484
- params.set('limit', String(args.limit));
560
+ params.set('limit', String(args?.limit));
561
+ if (args?.entityType)
562
+ params.set('entityType', String(args?.entityType));
563
+ if (args?.status)
564
+ params.set('status', String(args?.status));
485
565
  const res = await apiRequest(`/clients?${params.toString()}`);
486
- const clients = res.data || [];
566
+ let clients = res.data || [];
567
+ if (args?.tag) {
568
+ const searchTag = String(args.tag).toLowerCase();
569
+ clients = clients.filter((c) => Array.isArray(c.tags) && c.tags.some((t) => t.toLowerCase() === searchTag));
570
+ }
487
571
  if (clients.length === 0) {
488
572
  return {
489
- content: [{ type: 'text', text: 'No clients found matching the search criteria.' }],
573
+ content: [{ type: 'text', text: 'No clients found in the directory.' }],
490
574
  };
491
575
  }
492
576
  const formatted = clients
493
577
  .map((c) => {
494
- const company = c.company ? ` | Company: ${c.company}` : '';
578
+ const company = c.company ? ` (${c.company})` : '';
495
579
  const phone = c.phone ? ` | Phone: ${c.phone}` : '';
496
- return `• ${c.name} <${c.email}>${company}${phone}\n ID: ${c.id}`;
580
+ const entity = c.entityType ? ` | Entity: ${c.entityType}` : '';
581
+ const tags = c.tags?.length ? ` | Tags: [${c.tags.join(', ')}]` : '';
582
+ return `• ${c.name} <${c.email}>${company}${phone}${entity}${tags}\n ID: ${c.id}`;
497
583
  })
498
584
  .join('\n\n');
499
585
  return {
@@ -515,12 +601,28 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
515
601
  .map((r) => ` - [${r.status.toUpperCase()}] ${r.title} (ID: ${r.id})`)
516
602
  .join('\n');
517
603
  }
604
+ let contactsSummary = 'No linked contacts.';
605
+ if (c.linkedContacts && c.linkedContacts.length > 0) {
606
+ contactsSummary = c.linkedContacts
607
+ .map((lc) => ` - ${lc.name} (${lc.role}) ${lc.email ? `<${lc.email}>` : ''}`)
608
+ .join('\n');
609
+ }
518
610
  const report = `👤 Client Profile: ${c.name}\n` +
519
611
  `• ID: ${c.id}\n` +
520
612
  `• Email: ${c.email}\n` +
521
613
  `• Phone: ${c.phone || 'Not provided'}\n` +
522
614
  `• Company: ${c.company || 'Not provided'}\n` +
615
+ `• Entity Type: ${c.entityType || 'individual'}\n` +
616
+ `• Status: ${c.status || 'active'}\n` +
617
+ `• Fiscal Year End: ${c.fiscalYearEnd || '12/31'}\n` +
618
+ `• Filing Cadence: ${c.filingCadence || 'annual'}\n` +
619
+ `• State: ${c.stateOfFiling || 'N/A'}\n` +
620
+ `• Tax Year: ${c.taxYear || '2026'}\n` +
621
+ `• Masked Tax ID: ${c.maskedId || 'None'}\n` +
622
+ `• Tags: ${c.tags?.length ? `[${c.tags.join(', ')}]` : 'None'}\n` +
623
+ `• Pinned Note: ${c.pinnedNote ? `"${c.pinnedNote}"` : 'None'}\n` +
523
624
  `• Notes: ${c.notes || 'None'}\n\n` +
625
+ `Linked Contacts & Family:\n${contactsSummary}\n\n` +
524
626
  `Document Intake Requests:\n${requestsSummary}`;
525
627
  return {
526
628
  content: [{ type: 'text', text: report }],
@@ -533,6 +635,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
533
635
  phone: args?.phone,
534
636
  company: args?.company,
535
637
  notes: args?.notes,
638
+ entityType: args?.entityType,
639
+ status: args?.status,
640
+ fiscalYearEnd: args?.fiscalYearEnd,
641
+ filingCadence: args?.filingCadence,
642
+ stateOfFiling: args?.stateOfFiling,
643
+ taxYear: args?.taxYear,
644
+ tags: args?.tags,
645
+ pinnedNote: args?.pinnedNote,
646
+ qboId: args?.qboId,
647
+ taxSoftwareId: args?.taxSoftwareId,
648
+ maskedId: args?.maskedId,
649
+ linkedContacts: args?.linkedContacts,
536
650
  };
537
651
  const res = await apiRequest('/clients', {
538
652
  method: 'POST',
@@ -548,9 +662,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
548
662
  `• ID: ${c.id}\n` +
549
663
  `• Name: ${c.name}\n` +
550
664
  `• Email: ${c.email}\n` +
551
- `• Phone: ${c.phone || 'N/A'}\n` +
552
665
  `• Company: ${c.company || 'N/A'}\n` +
553
- `• Notes: ${c.notes || 'N/A'}`,
666
+ `• Entity: ${c.entityType || 'individual'}\n` +
667
+ `• Status: ${c.status || 'active'}\n` +
668
+ `• Tags: ${c.tags?.length ? `[${c.tags.join(', ')}]` : 'None'}\n` +
669
+ `• FYE: ${c.fiscalYearEnd || '12/31'}\n` +
670
+ `• Pinned Note: ${c.pinnedNote ? `"${c.pinnedNote}"` : 'None'}`,
554
671
  },
555
672
  ],
556
673
  };
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,9 +1,13 @@
1
1
  {
2
2
  "name": "@dropspot/mcp",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
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
5
  "type": "module",
6
6
  "homepage": "https://godropspot.com",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/officialdropspot/dropspot-mcp.git"
10
+ },
7
11
  "keywords": [
8
12
  "mcp",
9
13
  "model-context-protocol",
@@ -21,7 +25,10 @@
21
25
  "main": "dist/index.js",
22
26
  "files": [
23
27
  "dist",
24
- "README.md"
28
+ "README.md",
29
+ "LICENSE",
30
+ "smithery.yaml",
31
+ "glama.json"
25
32
  ],
26
33
  "publishConfig": {
27
34
  "access": "public"
@@ -32,14 +39,14 @@
32
39
  },
33
40
  "scripts": {
34
41
  "build": "tsc",
35
- "start": "node dist/index.js"
42
+ "start": "node dist/index.js",
43
+ "prepublishOnly": "npm run build"
36
44
  },
37
45
  "dependencies": {
38
46
  "@modelcontextprotocol/sdk": "^1.6.1",
39
47
  "zod": "^3.24.2"
40
48
  },
41
49
  "devDependencies": {
42
- "@dropspot/tsconfig": "workspace:*",
43
50
  "@types/node": "^22.10.1",
44
51
  "typescript": "~5.7.2"
45
52
  }
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"