viviscape-mcp 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # viviscape-mcp
2
2
 
3
- MCP server for the [ViviScape](https://viviscape.io) API exposes CRM, projects, companies, tasks, time tracking, notes, and insights as tools for Claude and other MCP clients.
3
+ MCP server for the [ViviScape](https://viviscape.io) API - exposes CRM, projects, companies, tasks, time tracking, notes, and insights as tools for Claude and other MCP clients.
4
4
 
5
5
  ## Installation
6
6
 
7
- No install needed run via `npx`:
7
+ No install needed - run via `npx`:
8
8
 
9
9
  ```bash
10
10
  npx viviscape-mcp
@@ -18,7 +18,7 @@ npm install -g viviscape-mcp
18
18
 
19
19
  ## Sign in
20
20
 
21
- Authentication is per-user, the same browser flow the ViviScape CLI uses no
21
+ Authentication is per-user, the same browser flow the ViviScape CLI uses - no
22
22
  API keys. Sign in once:
23
23
 
24
24
  ```bash
@@ -74,7 +74,7 @@ args = ["-y", "viviscape-mcp"]
74
74
 
75
75
  ## ChatGPT (Developer Mode / Apps SDK)
76
76
 
77
- ChatGPT only accepts **remote HTTP** MCP servers it does not run local stdio
77
+ ChatGPT only accepts **remote HTTP** MCP servers - it does not run local stdio
78
78
  processes. Bridge this server to an HTTP endpoint with
79
79
  [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) or
80
80
  [`supergateway`](https://www.npmjs.com/package/supergateway), then expose it
@@ -88,11 +88,11 @@ npx -y supergateway --stdio "npx -y viviscape-mcp" --port 8000
88
88
  ```
89
89
 
90
90
  The gateway shares the host's stored session, so everyone reaching that endpoint
91
- acts as the signed-in user put your own auth in front of it.
91
+ acts as the signed-in user - put your own auth in front of it.
92
92
 
93
93
  Expose `http://localhost:8000/sse` publicly, then in ChatGPT:
94
94
 
95
- **Settings Connectors Create Custom MCP server**
95
+ **Settings -> Connectors -> Create -> Custom MCP server**
96
96
  - **URL:** `https://your-public-host/sse`
97
97
  - **Auth:** none (or bearer, depending on your gateway)
98
98
 
@@ -100,16 +100,16 @@ Expose `http://localhost:8000/sse` publicly, then in ChatGPT:
100
100
 
101
101
  The server exposes tools across these domains:
102
102
 
103
- - **Prospects** `prospect_add`, `prospect_get`, `prospect_update`, `prospect_query`, follow-ups, notes
104
- - **Clients** `client_add`, `client_get`, `client_get_by_email`, `clients_by_company`
105
- - **Companies** `company_add`, `company_list`, `company_update`
106
- - **Projects** `project_get`, `project_list`, `project_list_active`, `project_staff`, `project_tasks`, `projects_by_company`
107
- - **Tasks** `task_add`, `task_get`, `task_update`, `tasks_open`, `tasks_pending`, `tasks_by_company`, `tasks_by_milestone`
108
- - **Time logs** `timelog_add`, `timelog_update`
109
- - **Notes** `note_add`, `note_get`, `note_update`, `note_remove`, `notes_mine`, `notes_query`
110
- - **Insights** hours by person/service/project, AI summary, person stats, time totals
111
- - **Account** `account_info`, `account_services`, `account_users`
112
- - **Auth** `auth_login`, `auth_status`, `auth_logout`
103
+ - **Prospects** - `prospect_add`, `prospect_get`, `prospect_update`, `prospect_query`, follow-ups, notes
104
+ - **Clients** - `client_add`, `client_get`, `client_get_by_email`, `clients_by_company`
105
+ - **Companies** - `company_add`, `company_list`, `company_update`
106
+ - **Projects** - `project_get`, `project_list`, `project_list_active`, `project_staff`, `project_tasks`, `projects_by_company`
107
+ - **Tasks** - `task_add`, `task_get`, `task_update`, `tasks_open`, `tasks_pending`, `tasks_by_company`, `tasks_by_milestone`
108
+ - **Time logs** - `timelog_add`, `timelog_update`
109
+ - **Notes** - `note_add`, `note_get`, `note_update`, `note_remove`, `notes_mine`, `notes_query`
110
+ - **Insights** - hours by person/service/project, AI summary, person stats, time totals
111
+ - **Account** - `account_info`, `account_services`, `account_users`
112
+ - **Auth** - `auth_login`, `auth_status`, `auth_logout`
113
113
 
114
114
  ## Development
115
115
 
@@ -242,7 +242,7 @@ export class ViviScapeClient {
242
242
  if (res.status >= 300 && res.status < 400)
243
243
  throw new SessionExpiredError();
244
244
  if (!res.ok) {
245
- const snippet = text.length > 400 ? `${text.slice(0, 400)}…` : text;
245
+ const snippet = text.length > 400 ? `${text.slice(0, 400)}...` : text;
246
246
  throw new ApiError(res.status, `API ${method} ${path} returned ${res.status}: ${snippet}`);
247
247
  }
248
248
  // Cookie-auth middleware bounces unauthenticated API calls to /login, which
@@ -267,7 +267,7 @@ export class ViviScapeClient {
267
267
  post(path, body) {
268
268
  return this.request('POST', path, body);
269
269
  }
270
- // ── Prospects ──────────────────────────────────────────────
270
+ // -- Prospects ----------------------------------------------
271
271
  async addProspect(data) {
272
272
  return this.post('prospect/add', {
273
273
  ...data,
@@ -304,7 +304,7 @@ export class ViviScapeClient {
304
304
  async removeProspect(prospectId) {
305
305
  return this.get(`prospect/remove/${prospectId}`);
306
306
  }
307
- // ── Prospect notes ─────────────────────────────────────────
307
+ // -- Prospect notes -----------------------------------------
308
308
  async addProspectNote(data) {
309
309
  return this.post('prospect/note/add', { user_id: this.userId, ...data });
310
310
  }
@@ -317,7 +317,7 @@ export class ViviScapeClient {
317
317
  async removeProspectNote(noteId) {
318
318
  return this.get(`prospect/note/remove/${noteId}`);
319
319
  }
320
- // ── Prospect follow-ups ────────────────────────────────────
320
+ // -- Prospect follow-ups ------------------------------------
321
321
  async addFollowup(data) {
322
322
  return this.post('prospect/followup/add', { user_id: this.userId, ...data });
323
323
  }
@@ -327,7 +327,7 @@ export class ViviScapeClient {
327
327
  async getFollowups(prospectId) {
328
328
  return this.get(`prospect/followups/list/${prospectId}`);
329
329
  }
330
- // ── Companies & clients ────────────────────────────────────
330
+ // -- Companies & clients ------------------------------------
331
331
  async listCompanies() {
332
332
  return this.get(`user/accounts?user_id=${this.userId}&account_id=${this.accountId}`);
333
333
  }
@@ -349,7 +349,7 @@ export class ViviScapeClient {
349
349
  async getClientByEmail(data) {
350
350
  return this.post('client/email', data);
351
351
  }
352
- // ── Projects (groups) ──────────────────────────────────────
352
+ // -- Projects (groups) --------------------------------------
353
353
  async getMyProjects() {
354
354
  return this.get(`user/groups/company?user_id=${this.userId}&account_id=${this.accountId}&companyid=0`);
355
355
  }
@@ -371,7 +371,7 @@ export class ViviScapeClient {
371
371
  async getActiveProjectsByUser(userId) {
372
372
  return this.get(`user/groups/active?user_id=${userId || this.userId}&account_id=${this.accountId}`);
373
373
  }
374
- // ── Tasks ──────────────────────────────────────────────────
374
+ // -- Tasks --------------------------------------------------
375
375
  async addTask(data) {
376
376
  return this.post('tasks/add', buildTaskPayload(data, this.ctx));
377
377
  }
@@ -411,14 +411,14 @@ export class ViviScapeClient {
411
411
  async getCompanyTasks(companyId) {
412
412
  return this.get(`company/tasks?company_id=${companyId}&user_id=${this.userId}`);
413
413
  }
414
- // ── Time logs ──────────────────────────────────────────────
414
+ // -- Time logs ----------------------------------------------
415
415
  async addTimeLog(data) {
416
416
  return this.post('logs/add', buildTimeLogPayload(data, this.ctx));
417
417
  }
418
418
  async updateTimeLog(data) {
419
419
  return this.post('logs/update', buildTimeLogPayload(data, this.ctx));
420
420
  }
421
- // ── Notes ──────────────────────────────────────────────────
421
+ // -- Notes --------------------------------------------------
422
422
  async getMyNotes() {
423
423
  return this.get('notes/me');
424
424
  }
@@ -451,7 +451,7 @@ export class ViviScapeClient {
451
451
  module: 'notes',
452
452
  });
453
453
  }
454
- // ── Account ────────────────────────────────────────────────
454
+ // -- Account ------------------------------------------------
455
455
  async getAccountInfo() {
456
456
  return this.get(`account/id/${this.accountId}`);
457
457
  }
@@ -464,7 +464,7 @@ export class ViviScapeClient {
464
464
  async getUsers() {
465
465
  return this.get(`account/users/${this.accountId}`);
466
466
  }
467
- // ── Insights ───────────────────────────────────────────────
467
+ // -- Insights -----------------------------------------------
468
468
  async getHoursByPerson(data) {
469
469
  const userId = Number(data.user_id) || this.userId;
470
470
  return this.get(`insights/logs/hours/person/${userId}?account_id=${this.accountId}` +
@@ -1,7 +1,7 @@
1
1
  import { Credentials } from './credentials.js';
2
2
  import { TokenStore } from './token-store.js';
3
3
  /**
4
- * Browser login over a loopback bridge the same flow as `vs auth login`
4
+ * Browser login over a loopback bridge - the same flow as `vs auth login`
5
5
  * (ViviScape.CLI/Auth/AuthService.cs): open /auth/cli/connect on ViviScape Work,
6
6
  * the page posts the signed-in session to a one-shot listener on 127.0.0.1.
7
7
  */
@@ -5,7 +5,7 @@ import { APP_NAME, CLI_CONNECT_PATH, baseUrl } from '../config.js';
5
5
  import { parseCredentials } from './credentials.js';
6
6
  import { createTokenStore } from './token-store.js';
7
7
  /**
8
- * Browser login over a loopback bridge the same flow as `vs auth login`
8
+ * Browser login over a loopback bridge - the same flow as `vs auth login`
9
9
  * (ViviScape.CLI/Auth/AuthService.cs): open /auth/cli/connect on ViviScape Work,
10
10
  * the page posts the signed-in session to a one-shot listener on 127.0.0.1.
11
11
  */
@@ -39,14 +39,14 @@ export class AuthService {
39
39
  if (!creds)
40
40
  throw new Error('The login bridge posted an unreadable payload.');
41
41
  if (posted !== state)
42
- throw new Error('State mismatch possible CSRF.');
42
+ throw new Error('State mismatch - possible CSRF.');
43
43
  creds.base_url = creds.base_url || baseUrl();
44
44
  this.store.write(creds);
45
45
  respond(res, 200, 'application/json', '{"ok":true}');
46
46
  settle({ creds });
47
47
  })
48
48
  .catch((err) => {
49
- // Reject the callback but keep listening a stray or hostile post
49
+ // Reject the callback but keep listening - a stray or hostile post
50
50
  // must not cancel a login the user is still completing.
51
51
  respond(res, 400, 'application/json', JSON.stringify({ ok: false, message: err.message }));
52
52
  log(`Rejected a login callback: ${err.message}`);
@@ -127,7 +127,7 @@ function respond(res, status, contentType, body) {
127
127
  'Access-Control-Allow-Origin': '*',
128
128
  'Access-Control-Allow-Headers': 'Content-Type',
129
129
  'Access-Control-Allow-Methods': 'POST,GET,OPTIONS',
130
- // Chrome Private Network Access let a public origin reach loopback.
130
+ // Chrome Private Network Access - let a public origin reach loopback.
131
131
  'Access-Control-Allow-Private-Network': 'true',
132
132
  'Access-Control-Max-Age': '600',
133
133
  });
@@ -1,6 +1,6 @@
1
1
  import { Credentials } from './credentials.js';
2
2
  /**
3
- * Plan gating mirrors ViviScape.CLI/Auth/Permissions.cs. The job here is a
3
+ * Plan gating - mirrors ViviScape.CLI/Auth/Permissions.cs. The job here is a
4
4
  * clean error when the account's tier can't reach a feature; role-level RBAC
5
5
  * stays on the server.
6
6
  */
@@ -1,6 +1,6 @@
1
1
  import { baseUrl } from '../config.js';
2
2
  /**
3
- * Plan gating mirrors ViviScape.CLI/Auth/Permissions.cs. The job here is a
3
+ * Plan gating - mirrors ViviScape.CLI/Auth/Permissions.cs. The job here is a
4
4
  * clean error when the account's tier can't reach a feature; role-level RBAC
5
5
  * stays on the server.
6
6
  */
@@ -38,9 +38,9 @@ export class PermissionDeniedError extends Error {
38
38
  export function requireFeature(feature, creds) {
39
39
  const min = MIN_PLAN[feature];
40
40
  if (min === undefined)
41
- return; // unknown allow
41
+ return; // unknown -> allow
42
42
  const forced = process.env.VS_FORCE_PLAN;
43
- // An unknown tier is not a denial only gate when the login told us the plan.
43
+ // An unknown tier is not a denial - only gate when the login told us the plan.
44
44
  if (!forced && !creds.plan_type)
45
45
  return;
46
46
  const have = forced ? parsePlan(forced) : parsePlan(creds.plan_type);
@@ -1,6 +1,6 @@
1
1
  import { Credentials } from './credentials.js';
2
2
  /**
3
- * Credential persistence Windows Credential Manager on win32 (the same store
3
+ * Credential persistence - Windows Credential Manager on win32 (the same store
4
4
  * and the same blob format the ViviScape CLI uses), a 0600 file elsewhere.
5
5
  * Mirrors ViviScape.CLI/Auth/TokenStore.cs.
6
6
  */
@@ -4,7 +4,7 @@ import { homedir, tmpdir } from 'node:os';
4
4
  import { join } from 'node:path';
5
5
  import { CLI_CREDENTIAL_KEY, CREDENTIAL_KEY } from '../config.js';
6
6
  import { parseCredentials } from './credentials.js';
7
- // ── Windows Credential Manager ────────────────────────────────
7
+ // -- Windows Credential Manager --------------------------------
8
8
  const CRED_PS1 = `param(
9
9
  [Parameter(Mandatory=$true)][ValidateSet('read','write','delete')][string]$Action,
10
10
  [Parameter(Mandatory=$true)][string]$Target,
@@ -123,7 +123,7 @@ class WindowsCredentialStore {
123
123
  });
124
124
  }
125
125
  }
126
- // ── Plain file store (non-Windows, or Credential Manager unavailable) ──
126
+ // -- Plain file store (non-Windows, or Credential Manager unavailable) --
127
127
  class FileStore {
128
128
  path;
129
129
  cliPath;
package/dist/config.d.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  /**
2
- * Shared configuration mirrors ViviScape.CLI/Config.cs so the MCP server and
2
+ * Shared configuration - mirrors ViviScape.CLI/Config.cs so the MCP server and
3
3
  * the CLI talk to the same host, the same API prefix, and the same login bridge.
4
4
  */
5
5
  export declare const APP_NAME = "viviscape-mcp";
6
6
  export declare const DISPLAY_NAME = "ViviScape MCP";
7
7
  /** Credential Manager / credential-file target for this client. */
8
8
  export declare const CREDENTIAL_KEY = "ViviScape.MCP:default";
9
- /** The CLI's target read as a fallback so `vs auth login` also signs in the MCP. */
9
+ /** The CLI's target - read as a fallback so `vs auth login` also signs in the MCP. */
10
10
  export declare const CLI_CREDENTIAL_KEY = "ViviScape.CLI:default";
11
11
  export declare const API_PREFIX = "/api/v1/core";
12
12
  export declare const CLI_CONNECT_PATH = "/auth/cli/connect";
package/dist/config.js CHANGED
@@ -1,12 +1,12 @@
1
1
  /**
2
- * Shared configuration mirrors ViviScape.CLI/Config.cs so the MCP server and
2
+ * Shared configuration - mirrors ViviScape.CLI/Config.cs so the MCP server and
3
3
  * the CLI talk to the same host, the same API prefix, and the same login bridge.
4
4
  */
5
5
  export const APP_NAME = 'viviscape-mcp';
6
6
  export const DISPLAY_NAME = 'ViviScape MCP';
7
7
  /** Credential Manager / credential-file target for this client. */
8
8
  export const CREDENTIAL_KEY = 'ViviScape.MCP:default';
9
- /** The CLI's target read as a fallback so `vs auth login` also signs in the MCP. */
9
+ /** The CLI's target - read as a fallback so `vs auth login` also signs in the MCP. */
10
10
  export const CLI_CREDENTIAL_KEY = 'ViviScape.CLI:default';
11
11
  export const API_PREFIX = '/api/v1/core';
12
12
  export const CLI_CONNECT_PATH = '/auth/cli/connect';
package/dist/index.js CHANGED
@@ -37,9 +37,9 @@ const server = new McpServer({
37
37
  function json(data) {
38
38
  return JSON.stringify(data, null, 2);
39
39
  }
40
- // ════════════════════════════════════════════════════════════
40
+ // ============================================================
41
41
  // AUTH
42
- // ════════════════════════════════════════════════════════════
42
+ // ============================================================
43
43
  server.tool('auth_status', 'Show the ViviScape session this server is using (user, account, role, plan)', {}, async () => {
44
44
  const creds = auth.current();
45
45
  if (!creds) {
@@ -98,9 +98,9 @@ server.tool('auth_logout', 'Clear the stored ViviScape session', {}, async () =>
98
98
  invalidateClient();
99
99
  return { content: [{ type: 'text', text: json({ signed_in: false }) }] };
100
100
  });
101
- // ════════════════════════════════════════════════════════════
101
+ // ============================================================
102
102
  // PROSPECTS
103
- // ════════════════════════════════════════════════════════════
103
+ // ============================================================
104
104
  server.tool('prospect_add', 'Add a new prospect/lead to the ViviScape CRM', {
105
105
  first_name: z.string().describe('First name'),
106
106
  last_name: z.string().describe('Last name'),
@@ -158,9 +158,9 @@ server.tool('prospect_remove', 'Remove a prospect from the CRM', { prospect_id:
158
158
  const result = await requireClient().removeProspect(prospect_id);
159
159
  return { content: [{ type: 'text', text: json(result) }] };
160
160
  });
161
- // ════════════════════════════════════════════════════════════
161
+ // ============================================================
162
162
  // PROSPECT NOTES
163
- // ════════════════════════════════════════════════════════════
163
+ // ============================================================
164
164
  server.tool('prospect_note_add', 'Add a note to a prospect', {
165
165
  prospect_id: z.number().describe('Prospect ID'),
166
166
  note: z.string().describe('Note content'),
@@ -184,9 +184,9 @@ server.tool('prospect_note_remove', 'Remove a prospect note', { note_id: z.numbe
184
184
  const result = await requireClient().removeProspectNote(note_id);
185
185
  return { content: [{ type: 'text', text: json(result) }] };
186
186
  });
187
- // ════════════════════════════════════════════════════════════
187
+ // ============================================================
188
188
  // PROSPECT FOLLOWUPS
189
- // ════════════════════════════════════════════════════════════
189
+ // ============================================================
190
190
  server.tool('prospect_followup_add', 'Add a followup record for a prospect', {
191
191
  prospect_id: z.number().describe('Prospect ID'),
192
192
  contact_method: z.string().optional().describe('Contact method (e.g., email, phone, meeting)'),
@@ -213,9 +213,9 @@ server.tool('prospect_followups_list', 'Get all followup records for a prospect'
213
213
  const result = await requireClient().getFollowups(prospect_id);
214
214
  return { content: [{ type: 'text', text: json(result) }] };
215
215
  });
216
- // ════════════════════════════════════════════════════════════
216
+ // ============================================================
217
217
  // COMPANIES & CLIENTS
218
- // ════════════════════════════════════════════════════════════
218
+ // ============================================================
219
219
  server.tool('company_list', 'List all companies', {}, async () => {
220
220
  const result = await requireClient().listCompanies();
221
221
  return { content: [{ type: 'text', text: json(result) }] };
@@ -269,9 +269,9 @@ server.tool('clients_by_company', 'Get all clients for a company', { company_id:
269
269
  const result = await requireClient().getClientsByCompany(company_id);
270
270
  return { content: [{ type: 'text', text: json(result) }] };
271
271
  });
272
- // ════════════════════════════════════════════════════════════
272
+ // ============================================================
273
273
  // PROJECTS & TASKS
274
- // ════════════════════════════════════════════════════════════
274
+ // ============================================================
275
275
  server.tool('project_list', 'Get all projects for current user', {}, async () => {
276
276
  const result = await requireClient().getMyProjects();
277
277
  return { content: [{ type: 'text', text: json(result) }] };
@@ -359,9 +359,9 @@ server.tool('projects_active_by_user', 'Get active projects for a specific user'
359
359
  const result = await requireClient().getActiveProjectsByUser(user_id);
360
360
  return { content: [{ type: 'text', text: json(result) }] };
361
361
  });
362
- // ════════════════════════════════════════════════════════════
362
+ // ============================================================
363
363
  // TIME TRACKING
364
- // ════════════════════════════════════════════════════════════
364
+ // ============================================================
365
365
  server.tool('timelog_add', 'Log time against a task. Duration uses shorthand format (e.g., 1h30m, 30m, 2h). Builds full LOG_Time payload.', {
366
366
  task_id: z.number().describe('Task ID to log time against'),
367
367
  user_id: z.number().optional().describe('User ID who performed the work. Defaults to Art Hicks (210)'),
@@ -391,9 +391,9 @@ server.tool('timelog_update', 'Update an existing time log entry. Builds full LO
391
391
  const result = await requireClient().updateTimeLog(params);
392
392
  return { content: [{ type: 'text', text: json(result) }] };
393
393
  });
394
- // ════════════════════════════════════════════════════════════
394
+ // ============================================================
395
395
  // NOTES
396
- // ════════════════════════════════════════════════════════════
396
+ // ============================================================
397
397
  server.tool('notes_mine', 'Get all notes for the current user', {}, async () => {
398
398
  const result = await requireClient().getMyNotes();
399
399
  return { content: [{ type: 'text', text: json(result) }] };
@@ -427,9 +427,9 @@ server.tool('notes_query', 'Search notes', {
427
427
  const result = await requireClient().queryNotes(params);
428
428
  return { content: [{ type: 'text', text: json(result) }] };
429
429
  });
430
- // ════════════════════════════════════════════════════════════
430
+ // ============================================================
431
431
  // ACCOUNT
432
- // ════════════════════════════════════════════════════════════
432
+ // ============================================================
433
433
  server.tool('account_info', 'Get account information', {}, async () => {
434
434
  const result = await requireClient().getAccountInfo();
435
435
  return { content: [{ type: 'text', text: json(result) }] };
@@ -442,9 +442,9 @@ server.tool('account_services', 'Get active services for the account', {}, async
442
442
  const result = await requireClient().getActiveServices();
443
443
  return { content: [{ type: 'text', text: json(result) }] };
444
444
  });
445
- // ════════════════════════════════════════════════════════════
445
+ // ============================================================
446
446
  // INSIGHTS
447
- // ════════════════════════════════════════════════════════════
447
+ // ============================================================
448
448
  server.tool('insights_hours_by_person', 'Get logged hours by person', {
449
449
  user_id: z.number().describe('User ID'),
450
450
  start_date: z.string().describe('Start date (ISO 8601)'),
@@ -527,10 +527,10 @@ server.tool('insights_all_users_time', 'Get time totals for all users', {}, asyn
527
527
  const result = await requireClient().getAllUsersTime();
528
528
  return { content: [{ type: 'text', text: json(result) }] };
529
529
  });
530
- // ════════════════════════════════════════════════════════════
530
+ // ============================================================
531
531
  // START
532
- // ════════════════════════════════════════════════════════════
533
- /** `viviscape-mcp login | logout | status` the interactive auth surface. */
532
+ // ============================================================
533
+ /** `viviscape-mcp login | logout | status` - the interactive auth surface. */
534
534
  async function runCommand(command) {
535
535
  switch (command) {
536
536
  case 'login': {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viviscape-mcp",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "MCP server for the ViviScape API — CRM, projects, companies, notes, and insights, authenticated as the signed-in ViviScape user",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",