viviscape-mcp 1.0.0 → 2.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 CHANGED
@@ -16,14 +16,36 @@ Or install globally:
16
16
  npm install -g viviscape-mcp
17
17
  ```
18
18
 
19
- ## Configuration
19
+ ## Sign in
20
+
21
+ Authentication is per-user, the same browser flow the ViviScape CLI uses — no
22
+ API keys. Sign in once:
23
+
24
+ ```bash
25
+ npx viviscape-mcp login
26
+ ```
27
+
28
+ A browser tab opens on ViviScape Work; confirm **Allow access** and the session
29
+ is stored in Windows Credential Manager (or `~/.viviscape/mcp-credentials.json`
30
+ on macOS/Linux). Every tool call then runs as *you*: your user id, account,
31
+ role, and plan come from the session, so tools see exactly the data you can see
32
+ in the app.
20
33
 
21
- Set the following environment variables:
34
+ ```bash
35
+ npx viviscape-mcp status # who am I, which account, role, plan
36
+ npx viviscape-mcp logout # clear the stored session
37
+ ```
38
+
39
+ If you already ran `vs auth login` with the [ViviScape CLI](https://viviscape.io),
40
+ that session is picked up automatically. Inside an MCP client you can also call
41
+ the `auth_login`, `auth_status`, and `auth_logout` tools. Sessions expire; when
42
+ one does, tools report it and you re-run `login`.
43
+
44
+ ## Configuration
22
45
 
23
46
  | Variable | Required | Default | Description |
24
47
  |----------|----------|---------|-------------|
25
- | `VIVISCAPE_API_KEY` | yes | | Your ViviScape API key |
26
- | `VIVISCAPE_API_URL` | no | `https://api.viviscape.io` | API base URL |
48
+ | `VIVISCAPE_BASE_URL` | no | `https://work.viviscape.io` | ViviScape Work base URL |
27
49
 
28
50
  ## Claude Desktop / Claude Code
29
51
 
@@ -34,15 +56,46 @@ Add to your MCP client config (e.g. `claude_desktop_config.json` or `.mcp.json`)
34
56
  "mcpServers": {
35
57
  "viviscape": {
36
58
  "command": "npx",
37
- "args": ["-y", "viviscape-mcp"],
38
- "env": {
39
- "VIVISCAPE_API_KEY": "your-api-key-here"
40
- }
59
+ "args": ["-y", "viviscape-mcp"]
41
60
  }
42
61
  }
43
62
  }
44
63
  ```
45
64
 
65
+ ## OpenAI Codex CLI
66
+
67
+ Codex accepts stdio MCP servers directly. Add to `~/.codex/config.toml`:
68
+
69
+ ```toml
70
+ [mcp_servers.viviscape]
71
+ command = "npx"
72
+ args = ["-y", "viviscape-mcp"]
73
+ ```
74
+
75
+ ## ChatGPT (Developer Mode / Apps SDK)
76
+
77
+ ChatGPT only accepts **remote HTTP** MCP servers — it does not run local stdio
78
+ processes. Bridge this server to an HTTP endpoint with
79
+ [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) or
80
+ [`supergateway`](https://www.npmjs.com/package/supergateway), then expose it
81
+ publicly (Cloudflare Tunnel, ngrok, or deploy to a host).
82
+
83
+ Example with `supergateway`:
84
+
85
+ ```bash
86
+ npx viviscape-mcp login # once, on the host running the gateway
87
+ npx -y supergateway --stdio "npx -y viviscape-mcp" --port 8000
88
+ ```
89
+
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.
92
+
93
+ Expose `http://localhost:8000/sse` publicly, then in ChatGPT:
94
+
95
+ **Settings → Connectors → Create → Custom MCP server**
96
+ - **URL:** `https://your-public-host/sse`
97
+ - **Auth:** none (or bearer, depending on your gateway)
98
+
46
99
  ## Tools
47
100
 
48
101
  The server exposes tools across these domains:
@@ -56,6 +109,7 @@ The server exposes tools across these domains:
56
109
  - **Notes** — `note_add`, `note_get`, `note_update`, `note_remove`, `notes_mine`, `notes_query`
57
110
  - **Insights** — hours by person/service/project, AI summary, person stats, time totals
58
111
  - **Account** — `account_info`, `account_services`, `account_users`
112
+ - **Auth** — `auth_login`, `auth_status`, `auth_logout`
59
113
 
60
114
  ## Development
61
115
 
@@ -1,8 +1,28 @@
1
+ import { Credentials } from './auth/credentials.js';
2
+ /** Raised when the stored session is rejected or bounced to the login page. */
3
+ export declare class SessionExpiredError extends Error {
4
+ constructor();
5
+ }
6
+ export declare class ApiError extends Error {
7
+ status: number;
8
+ constructor(status: number, message: string);
9
+ }
10
+ /**
11
+ * Client for the ViviScape Work core API. Authenticates exactly like the
12
+ * ViviScape CLI: the signed-in user's bearer token plus the user_id / pid
13
+ * context headers the core API falls back to.
14
+ */
1
15
  export declare class ViviScapeClient {
16
+ private creds;
2
17
  private baseUrl;
3
- private apiKey;
4
- constructor(baseUrl: string, apiKey: string);
18
+ constructor(creds: Credentials);
19
+ get userId(): number;
20
+ get accountId(): number;
21
+ get session(): Credentials;
22
+ private get ctx();
5
23
  private request;
24
+ private get;
25
+ private post;
6
26
  addProspect(data: Record<string, unknown>): Promise<unknown>;
7
27
  updateProspect(data: Record<string, unknown>): Promise<unknown>;
8
28
  getProspect(prospectId: number): Promise<unknown>;
@@ -30,6 +50,8 @@ export declare class ViviScapeClient {
30
50
  getActiveProjects(): Promise<Record<string, unknown>[]>;
31
51
  getProjectById(projectId: number): Promise<unknown>;
32
52
  getProjectStaff(projectId: number): Promise<unknown>;
53
+ getProjectsByCompany(userId: number, companyId: number): Promise<unknown>;
54
+ getActiveProjectsByUser(userId: number): Promise<unknown>;
33
55
  addTask(data: Record<string, unknown>): Promise<unknown>;
34
56
  updateTask(data: Record<string, unknown>): Promise<unknown>;
35
57
  getProjectTasks(projectId: number): Promise<unknown>;
@@ -39,15 +61,13 @@ export declare class ViviScapeClient {
39
61
  getTasksByMilestone(milestoneId: number): Promise<unknown>;
40
62
  getTasksByGroupAndUser(groupId: number, userId: number): Promise<unknown>;
41
63
  getCompanyTasks(companyId: number): Promise<unknown>;
42
- getProjectsByCompany(userId: number, companyId: number): Promise<unknown>;
43
- getActiveProjectsByUser(userId: number): Promise<unknown>;
44
64
  addTimeLog(data: Record<string, unknown>): Promise<unknown>;
45
65
  updateTimeLog(data: Record<string, unknown>): Promise<unknown>;
46
66
  getMyNotes(): Promise<unknown>;
47
- getNoteById(noteId: number): Promise<unknown>;
67
+ getNoteById(noteId: number | string): Promise<unknown>;
48
68
  addNote(data: Record<string, unknown>): Promise<unknown>;
49
69
  updateNote(data: Record<string, unknown>): Promise<unknown>;
50
- removeNote(noteId: number): Promise<unknown>;
70
+ removeNote(noteId: number | string): Promise<unknown>;
51
71
  queryNotes(data: Record<string, unknown>): Promise<unknown>;
52
72
  getAccountInfo(): Promise<unknown>;
53
73
  getActiveServices(): Promise<unknown>;