@dversum/mcp-server 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.
Files changed (78) hide show
  1. package/README.md +235 -0
  2. package/dist/bin/dversum-mcp.d.ts +3 -0
  3. package/dist/bin/dversum-mcp.d.ts.map +1 -0
  4. package/dist/bin/dversum-mcp.js +7 -0
  5. package/dist/bin/dversum-mcp.js.map +1 -0
  6. package/dist/src/client.d.ts +13 -0
  7. package/dist/src/client.d.ts.map +1 -0
  8. package/dist/src/client.js +66 -0
  9. package/dist/src/client.js.map +1 -0
  10. package/dist/src/config.d.ts +6 -0
  11. package/dist/src/config.d.ts.map +1 -0
  12. package/dist/src/config.js +20 -0
  13. package/dist/src/config.js.map +1 -0
  14. package/dist/src/context.d.ts +8 -0
  15. package/dist/src/context.d.ts.map +1 -0
  16. package/dist/src/context.js +6 -0
  17. package/dist/src/context.js.map +1 -0
  18. package/dist/src/index.d.ts +7 -0
  19. package/dist/src/index.d.ts.map +1 -0
  20. package/dist/src/index.js +128 -0
  21. package/dist/src/index.js.map +1 -0
  22. package/dist/src/tools/absences.d.ts +4 -0
  23. package/dist/src/tools/absences.d.ts.map +1 -0
  24. package/dist/src/tools/absences.js +44 -0
  25. package/dist/src/tools/absences.js.map +1 -0
  26. package/dist/src/tools/calendar.d.ts +4 -0
  27. package/dist/src/tools/calendar.d.ts.map +1 -0
  28. package/dist/src/tools/calendar.js +69 -0
  29. package/dist/src/tools/calendar.js.map +1 -0
  30. package/dist/src/tools/clients.d.ts +4 -0
  31. package/dist/src/tools/clients.d.ts.map +1 -0
  32. package/dist/src/tools/clients.js +72 -0
  33. package/dist/src/tools/clients.js.map +1 -0
  34. package/dist/src/tools/contacts.d.ts +4 -0
  35. package/dist/src/tools/contacts.d.ts.map +1 -0
  36. package/dist/src/tools/contacts.js +40 -0
  37. package/dist/src/tools/contacts.js.map +1 -0
  38. package/dist/src/tools/finance.d.ts +4 -0
  39. package/dist/src/tools/finance.d.ts.map +1 -0
  40. package/dist/src/tools/finance.js +67 -0
  41. package/dist/src/tools/finance.js.map +1 -0
  42. package/dist/src/tools/invoices.d.ts +4 -0
  43. package/dist/src/tools/invoices.d.ts.map +1 -0
  44. package/dist/src/tools/invoices.js +97 -0
  45. package/dist/src/tools/invoices.js.map +1 -0
  46. package/dist/src/tools/notifications.d.ts +4 -0
  47. package/dist/src/tools/notifications.d.ts.map +1 -0
  48. package/dist/src/tools/notifications.js +24 -0
  49. package/dist/src/tools/notifications.js.map +1 -0
  50. package/dist/src/tools/organization.d.ts +4 -0
  51. package/dist/src/tools/organization.d.ts.map +1 -0
  52. package/dist/src/tools/organization.js +20 -0
  53. package/dist/src/tools/organization.js.map +1 -0
  54. package/dist/src/tools/pages.d.ts +4 -0
  55. package/dist/src/tools/pages.d.ts.map +1 -0
  56. package/dist/src/tools/pages.js +46 -0
  57. package/dist/src/tools/pages.js.map +1 -0
  58. package/dist/src/tools/projects.d.ts +4 -0
  59. package/dist/src/tools/projects.d.ts.map +1 -0
  60. package/dist/src/tools/projects.js +49 -0
  61. package/dist/src/tools/projects.js.map +1 -0
  62. package/dist/src/tools/quotes.d.ts +4 -0
  63. package/dist/src/tools/quotes.d.ts.map +1 -0
  64. package/dist/src/tools/quotes.js +62 -0
  65. package/dist/src/tools/quotes.js.map +1 -0
  66. package/dist/src/tools/storage.d.ts +4 -0
  67. package/dist/src/tools/storage.d.ts.map +1 -0
  68. package/dist/src/tools/storage.js +45 -0
  69. package/dist/src/tools/storage.js.map +1 -0
  70. package/dist/src/tools/tasks.d.ts +4 -0
  71. package/dist/src/tools/tasks.d.ts.map +1 -0
  72. package/dist/src/tools/tasks.js +72 -0
  73. package/dist/src/tools/tasks.js.map +1 -0
  74. package/dist/src/tools/time.d.ts +4 -0
  75. package/dist/src/tools/time.d.ts.map +1 -0
  76. package/dist/src/tools/time.js +81 -0
  77. package/dist/src/tools/time.js.map +1 -0
  78. package/package.json +47 -0
package/README.md ADDED
@@ -0,0 +1,235 @@
1
+ # @dversum/mcp-server
2
+
3
+ Official [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server for the **dVersum** business management API. Lets AI assistants like Claude Desktop, Cursor, and Windsurf interact with your dVersum workspace — managing clients, projects, tasks, invoices, time tracking, and more.
4
+
5
+ ## Quick Start
6
+
7
+ ### Claude Desktop
8
+
9
+ Add this to your Claude Desktop configuration (`~/Library/Application Support/Claude/claude_desktop_config.json`):
10
+
11
+ ```json
12
+ {
13
+ "mcpServers": {
14
+ "dversum": {
15
+ "command": "npx",
16
+ "args": ["-y", "@dversum/mcp-server"],
17
+ "env": {
18
+ "DVERSUM_API_URL": "https://api.dversum.com/api/v1",
19
+ "DVERSUM_API_TOKEN": "your-jwt-token"
20
+ }
21
+ }
22
+ }
23
+ }
24
+ ```
25
+
26
+ ### Cursor / Windsurf
27
+
28
+ Add to your MCP settings:
29
+
30
+ ```json
31
+ {
32
+ "mcpServers": {
33
+ "dversum": {
34
+ "command": "npx",
35
+ "args": ["-y", "@dversum/mcp-server"],
36
+ "env": {
37
+ "DVERSUM_API_URL": "https://api.dversum.com/api/v1",
38
+ "DVERSUM_API_TOKEN": "your-jwt-token"
39
+ }
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ ## Docker (Production)
46
+
47
+ ### Quick start
48
+
49
+ ```bash
50
+ cd mcp-server
51
+
52
+ # Create .env file
53
+ echo "DVERSUM_API_URL=https://api.dversum.com/api/v1" > .env
54
+ echo "DVERSUM_API_TOKEN=your-jwt-token" >> .env
55
+
56
+ # Run
57
+ docker compose up -d
58
+ ```
59
+
60
+ The server starts on port **3100** with a health check at `/health` and the MCP endpoint at `/mcp`.
61
+
62
+ ### Build & run manually
63
+
64
+ ```bash
65
+ docker build -t dversum-mcp .
66
+ docker run -d \
67
+ -p 3100:3100 \
68
+ -e DVERSUM_API_URL=https://api.dversum.com/api/v1 \
69
+ -e DVERSUM_API_TOKEN=your-jwt-token \
70
+ --name dversum-mcp \
71
+ --restart unless-stopped \
72
+ dversum-mcp
73
+ ```
74
+
75
+ ### Connect remote MCP to Claude Desktop
76
+
77
+ Once the Docker container is running, point Claude Desktop to the remote endpoint:
78
+
79
+ ```json
80
+ {
81
+ "mcpServers": {
82
+ "dversum": {
83
+ "url": "http://your-server:3100/mcp"
84
+ }
85
+ }
86
+ }
87
+ ```
88
+
89
+ ## Environment Variables
90
+
91
+ | Variable | Required | Description |
92
+ |----------|----------|-------------|
93
+ | `DVERSUM_API_URL` | Yes | Base URL of your dVersum API (e.g. `https://api.dversum.com/api/v1`) |
94
+ | `DVERSUM_API_TOKEN` | Yes | Your JWT authentication token |
95
+ | `MCP_TRANSPORT` | No | `stdio` (default) or `http` (for Docker/remote) |
96
+ | `MCP_PORT` | No | HTTP port when using `http` transport (default: `3100`) |
97
+
98
+ ## Available Tools (53)
99
+
100
+ ### Clients (CRM)
101
+ | Tool | Description |
102
+ |------|-------------|
103
+ | `list_clients` | List all clients with pagination |
104
+ | `get_client` | Get client details |
105
+ | `create_client` | Create a new client |
106
+ | `update_client` | Update client details |
107
+ | `delete_client` | Delete a client |
108
+
109
+ ### Contacts
110
+ | Tool | Description |
111
+ |------|-------------|
112
+ | `list_contacts` | List all contacts |
113
+ | `get_contact` | Get contact details |
114
+ | `create_contact` | Create a new contact |
115
+
116
+ ### Projects
117
+ | Tool | Description |
118
+ |------|-------------|
119
+ | `list_projects` | List all projects |
120
+ | `get_project` | Get project details |
121
+ | `create_project` | Create a new project |
122
+ | `get_project_board` | Get full kanban board (columns + tasks) |
123
+
124
+ ### Tasks
125
+ | Tool | Description |
126
+ |------|-------------|
127
+ | `get_task` | Get task details (assignees, subtasks, tags) |
128
+ | `create_task` | Create a task in a project column |
129
+ | `update_task` | Update task properties |
130
+ | `move_task` | Move task to a different column |
131
+ | `assign_task` | Add an assignee to a task |
132
+ | `list_task_comments` | List comments on a task |
133
+
134
+ ### Time Tracking
135
+ | Tool | Description |
136
+ |------|-------------|
137
+ | `list_time_entries` | List time entries (filter by date, project) |
138
+ | `create_time_entry` | Log a completed time entry |
139
+ | `start_timer` | Start a running timer |
140
+ | `stop_timer` | Stop a running timer |
141
+ | `get_running_timer` | Get the currently running timer |
142
+ | `get_time_stats` | Get time tracking statistics |
143
+
144
+ ### Calendar
145
+ | Tool | Description |
146
+ |------|-------------|
147
+ | `list_events` | List calendar events in a date range |
148
+ | `get_event` | Get event details |
149
+ | `create_event` | Create a calendar event |
150
+ | `update_event` | Update an event |
151
+ | `delete_event` | Delete an event |
152
+
153
+ ### Invoices
154
+ | Tool | Description |
155
+ |------|-------------|
156
+ | `list_invoices` | List invoices (filter by status, client, type) |
157
+ | `get_invoice` | Get invoice with line items and totals |
158
+ | `create_invoice` | Create a draft invoice |
159
+ | `update_invoice_status` | Change invoice status |
160
+ | `send_invoice_email` | Send invoice via email |
161
+ | `create_invoice_from_time` | Create invoice from tracked time |
162
+
163
+ ### Quotes
164
+ | Tool | Description |
165
+ |------|-------------|
166
+ | `list_quotes` | List quotes/proposals |
167
+ | `get_quote` | Get quote with line items |
168
+ | `create_quote` | Create a draft quote |
169
+ | `convert_quote_to_invoice` | Convert accepted quote to invoice |
170
+
171
+ ### Finance
172
+ | Tool | Description |
173
+ |------|-------------|
174
+ | `get_finance_overview` | Monthly revenue vs expenses |
175
+ | `get_vat_summary` | USt-Voranmeldung (KZ 81/86/66/83) |
176
+ | `list_received_invoices` | List incoming invoices |
177
+ | `list_suppliers` | List all suppliers |
178
+
179
+ ### Team Planning (Absences)
180
+ | Tool | Description |
181
+ |------|-------------|
182
+ | `list_absences` | List team absences |
183
+ | `create_absence` | Create an absence entry |
184
+ | `get_vacation_stats` | Get vacation quota/usage stats |
185
+
186
+ ### Pages
187
+ | Tool | Description |
188
+ |------|-------------|
189
+ | `list_pages` | List all pages |
190
+ | `get_page` | Get page with content |
191
+ | `create_page` | Create a new page |
192
+ | `update_page_content` | Update page content |
193
+
194
+ ### File Storage
195
+ | Tool | Description |
196
+ |------|-------------|
197
+ | `list_files` | List files in a folder |
198
+ | `list_folders` | List folders |
199
+ | `create_folder` | Create a new folder |
200
+ | `get_folder_tree` | Get full folder hierarchy |
201
+
202
+ ### Notifications
203
+ | Tool | Description |
204
+ |------|-------------|
205
+ | `list_notifications` | List recent notifications |
206
+ | `get_unread_count` | Get unread notification count |
207
+
208
+ ### Organization
209
+ | Tool | Description |
210
+ |------|-------------|
211
+ | `get_organization` | Get organization details |
212
+ | `list_members` | List team members |
213
+
214
+ ## Development
215
+
216
+ ```bash
217
+ # Clone the repo
218
+ git clone https://github.com/dversum/dversum.git
219
+ cd dversum/mcp-server
220
+
221
+ # Install dependencies
222
+ npm install
223
+
224
+ # Build
225
+ npm run build
226
+
227
+ # Run locally
228
+ DVERSUM_API_URL=http://localhost:8080/api/v1 \
229
+ DVERSUM_API_TOKEN=your-jwt-token \
230
+ node dist/bin/dversum-mcp.js
231
+ ```
232
+
233
+ ## License
234
+
235
+ MIT
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=dversum-mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dversum-mcp.d.ts","sourceRoot":"","sources":["../../bin/dversum-mcp.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import { main } from "../src/index.js";
3
+ main().catch((error) => {
4
+ console.error("Fatal error:", error.message);
5
+ process.exit(1);
6
+ });
7
+ //# sourceMappingURL=dversum-mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dversum-mcp.js","sourceRoot":"","sources":["../../bin/dversum-mcp.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ export declare class DversumClient {
2
+ private baseUrl;
3
+ private fallbackToken;
4
+ constructor(baseUrl: string, fallbackToken: string);
5
+ private buildUrl;
6
+ private request;
7
+ get<T>(path: string, params?: Record<string, string>): Promise<T>;
8
+ post<T>(path: string, body?: unknown): Promise<T>;
9
+ put<T>(path: string, body?: unknown): Promise<T>;
10
+ patch<T>(path: string, body?: unknown): Promise<T>;
11
+ delete(path: string): Promise<void>;
12
+ }
13
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAEA,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,aAAa,CAAS;gBAElB,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM;IAKlD,OAAO,CAAC,QAAQ;YAYF,OAAO;IA6Cf,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAIjE,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIjD,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIhD,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIlD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG1C"}
@@ -0,0 +1,66 @@
1
+ import { getRequestToken } from "./context.js";
2
+ export class DversumClient {
3
+ baseUrl;
4
+ fallbackToken;
5
+ constructor(baseUrl, fallbackToken) {
6
+ this.baseUrl = baseUrl;
7
+ this.fallbackToken = fallbackToken;
8
+ }
9
+ buildUrl(path, params) {
10
+ const url = new URL(`${this.baseUrl}${path}`);
11
+ if (params) {
12
+ for (const [key, value] of Object.entries(params)) {
13
+ if (value !== undefined && value !== null && value !== "") {
14
+ url.searchParams.set(key, value);
15
+ }
16
+ }
17
+ }
18
+ return url.toString();
19
+ }
20
+ async request(method, path, options) {
21
+ const url = this.buildUrl(path, options?.params);
22
+ const token = getRequestToken() ?? this.fallbackToken;
23
+ const headers = {
24
+ Authorization: `Bearer ${token}`,
25
+ "Content-Type": "application/json",
26
+ };
27
+ const fetchOptions = { method, headers };
28
+ if (options?.body !== undefined) {
29
+ fetchOptions.body = JSON.stringify(options.body);
30
+ }
31
+ const response = await fetch(url, fetchOptions);
32
+ if (!response.ok) {
33
+ let errorMessage = `API error ${response.status}: ${response.statusText}`;
34
+ try {
35
+ const errorBody = (await response.json());
36
+ if (errorBody.error) {
37
+ errorMessage = errorBody.error;
38
+ }
39
+ }
40
+ catch {
41
+ // Use default error message
42
+ }
43
+ throw new Error(errorMessage);
44
+ }
45
+ if (response.status === 204) {
46
+ return undefined;
47
+ }
48
+ return (await response.json());
49
+ }
50
+ async get(path, params) {
51
+ return this.request("GET", path, { params });
52
+ }
53
+ async post(path, body) {
54
+ return this.request("POST", path, { body });
55
+ }
56
+ async put(path, body) {
57
+ return this.request("PUT", path, { body });
58
+ }
59
+ async patch(path, body) {
60
+ return this.request("PATCH", path, { body });
61
+ }
62
+ async delete(path) {
63
+ await this.request("DELETE", path);
64
+ }
65
+ }
66
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export interface Config {
2
+ apiUrl: string;
3
+ apiToken: string;
4
+ }
5
+ export declare function loadConfig(): Config;
6
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,UAAU,IAAI,MAAM,CAyBnC"}
@@ -0,0 +1,20 @@
1
+ export function loadConfig() {
2
+ const apiUrl = process.env.DVERSUM_API_URL;
3
+ const apiToken = process.env.DVERSUM_API_TOKEN || "";
4
+ const transport = process.env.MCP_TRANSPORT || "stdio";
5
+ if (!apiUrl) {
6
+ throw new Error("DVERSUM_API_URL environment variable is required.\n" +
7
+ "Set it to your dVersum API base URL, e.g. https://api.dversum.com/api/v1");
8
+ }
9
+ // Token is required for stdio mode (single user), optional for HTTP mode (per-user auth via headers)
10
+ if (!apiToken && transport !== "http") {
11
+ throw new Error("DVERSUM_API_TOKEN environment variable is required for stdio mode.\n" +
12
+ "Set it to your dVersum JWT authentication token.\n" +
13
+ "In HTTP mode (MCP_TRANSPORT=http), tokens are provided per-request via Authorization header.");
14
+ }
15
+ return {
16
+ apiUrl: apiUrl.replace(/\/+$/, ""),
17
+ apiToken,
18
+ };
19
+ }
20
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,UAAU;IACxB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAC3C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC;IACrD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,OAAO,CAAC;IAEvD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,qDAAqD;YACnD,0EAA0E,CAC7E,CAAC;IACJ,CAAC;IAED,qGAAqG;IACrG,IAAI,CAAC,QAAQ,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CACb,sEAAsE;YACpE,oDAAoD;YACpD,8FAA8F,CACjG,CAAC;IACJ,CAAC;IAED,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QAClC,QAAQ;KACT,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ interface RequestStore {
3
+ token: string;
4
+ }
5
+ export declare const requestContext: AsyncLocalStorage<RequestStore>;
6
+ export declare function getRequestToken(): string | undefined;
7
+ export {};
8
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,UAAU,YAAY;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,cAAc,iCAAwC,CAAC;AAEpE,wBAAgB,eAAe,IAAI,MAAM,GAAG,SAAS,CAEpD"}
@@ -0,0 +1,6 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ export const requestContext = new AsyncLocalStorage();
3
+ export function getRequestToken() {
4
+ return requestContext.getStore()?.token;
5
+ }
6
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAMrD,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,iBAAiB,EAAgB,CAAC;AAEpE,MAAM,UAAU,eAAe;IAC7B,OAAO,cAAc,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function createServer(): {
3
+ server: McpServer;
4
+ fallbackToken: string;
5
+ };
6
+ export declare function main(): Promise<void>;
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAuCpE,wBAAgB,YAAY,IAAI;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAY3E;AAoGD,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAQ1C"}
@@ -0,0 +1,128 @@
1
+ import { createServer as createHttpServer } from "node:http";
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
5
+ import { DversumClient } from "./client.js";
6
+ import { loadConfig } from "./config.js";
7
+ import { requestContext } from "./context.js";
8
+ import { registerClientTools } from "./tools/clients.js";
9
+ import { registerContactTools } from "./tools/contacts.js";
10
+ import { registerProjectTools } from "./tools/projects.js";
11
+ import { registerTaskTools } from "./tools/tasks.js";
12
+ import { registerTimeTools } from "./tools/time.js";
13
+ import { registerCalendarTools } from "./tools/calendar.js";
14
+ import { registerInvoiceTools } from "./tools/invoices.js";
15
+ import { registerQuoteTools } from "./tools/quotes.js";
16
+ import { registerFinanceTools } from "./tools/finance.js";
17
+ import { registerAbsenceTools } from "./tools/absences.js";
18
+ import { registerPageTools } from "./tools/pages.js";
19
+ import { registerStorageTools } from "./tools/storage.js";
20
+ import { registerNotificationTools } from "./tools/notifications.js";
21
+ import { registerOrganizationTools } from "./tools/organization.js";
22
+ function registerAllTools(server, apiClient) {
23
+ registerClientTools(server, apiClient);
24
+ registerContactTools(server, apiClient);
25
+ registerProjectTools(server, apiClient);
26
+ registerTaskTools(server, apiClient);
27
+ registerTimeTools(server, apiClient);
28
+ registerCalendarTools(server, apiClient);
29
+ registerInvoiceTools(server, apiClient);
30
+ registerQuoteTools(server, apiClient);
31
+ registerFinanceTools(server, apiClient);
32
+ registerAbsenceTools(server, apiClient);
33
+ registerPageTools(server, apiClient);
34
+ registerStorageTools(server, apiClient);
35
+ registerNotificationTools(server, apiClient);
36
+ registerOrganizationTools(server, apiClient);
37
+ }
38
+ export function createServer() {
39
+ const config = loadConfig();
40
+ const server = new McpServer({
41
+ name: "dversum",
42
+ version: "1.0.0",
43
+ });
44
+ const apiClient = new DversumClient(config.apiUrl, config.apiToken);
45
+ registerAllTools(server, apiClient);
46
+ return { server, fallbackToken: config.apiToken };
47
+ }
48
+ async function startStdio() {
49
+ const { server } = createServer();
50
+ const transport = new StdioServerTransport();
51
+ await server.connect(transport);
52
+ }
53
+ async function handleHttpRequest(req, res, config, fallbackToken) {
54
+ // CORS headers for remote access
55
+ res.setHeader("Access-Control-Allow-Origin", "*");
56
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, DELETE");
57
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, mcp-session-id");
58
+ if (req.method === "OPTIONS") {
59
+ res.writeHead(204);
60
+ res.end();
61
+ return;
62
+ }
63
+ // Health check
64
+ if (req.url === "/health" && req.method === "GET") {
65
+ res.writeHead(200, { "Content-Type": "application/json" });
66
+ res.end(JSON.stringify({ status: "ok", server: "dversum-mcp" }));
67
+ return;
68
+ }
69
+ // MCP endpoint
70
+ if (req.url === "/mcp") {
71
+ console.log(`[MCP] ${req.method} /mcp from ${req.headers["user-agent"] || "unknown"}`);
72
+ // Extract Bearer token from Authorization header
73
+ const authHeader = req.headers.authorization;
74
+ const token = authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : undefined;
75
+ const effectiveToken = token || fallbackToken;
76
+ if (!effectiveToken) {
77
+ res.writeHead(401, { "Content-Type": "application/json" });
78
+ res.end(JSON.stringify({
79
+ error: "Authorization required. Send a Bearer token in the Authorization header.",
80
+ }));
81
+ return;
82
+ }
83
+ // Stateless mode: create a new server + transport per request
84
+ const server = new McpServer({ name: "dversum", version: "1.0.0" });
85
+ const apiClient = new DversumClient(config.apiUrl, config.apiToken);
86
+ registerAllTools(server, apiClient);
87
+ const transport = new StreamableHTTPServerTransport({
88
+ sessionIdGenerator: undefined, // Stateless mode
89
+ });
90
+ await server.connect(transport);
91
+ await requestContext.run({ token: effectiveToken }, async () => {
92
+ await transport.handleRequest(req, res);
93
+ });
94
+ return;
95
+ }
96
+ res.writeHead(404);
97
+ res.end("Not found");
98
+ }
99
+ async function startHttp() {
100
+ const config = loadConfig();
101
+ const fallbackToken = config.apiToken;
102
+ const port = parseInt(process.env.MCP_PORT || "3100", 10);
103
+ // Use non-async callback to properly catch all errors
104
+ const httpServer = createHttpServer((req, res) => {
105
+ handleHttpRequest(req, res, config, fallbackToken).catch((err) => {
106
+ console.error("[MCP] Unhandled error:", err);
107
+ if (!res.headersSent) {
108
+ res.writeHead(500, { "Content-Type": "application/json" });
109
+ res.end(JSON.stringify({ error: "Internal server error" }));
110
+ }
111
+ });
112
+ });
113
+ httpServer.listen(port, () => {
114
+ console.log(`dVersum MCP server (HTTP) running on port ${port}`);
115
+ console.log(`MCP endpoint: http://localhost:${port}/mcp`);
116
+ console.log(`Health check: http://localhost:${port}/health`);
117
+ });
118
+ }
119
+ export async function main() {
120
+ const transport = process.env.MCP_TRANSPORT || "stdio";
121
+ if (transport === "http") {
122
+ await startHttp();
123
+ }
124
+ else {
125
+ await startStdio();
126
+ }
127
+ }
128
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { DversumClient } from "../client.js";
3
+ export declare function registerAbsenceTools(server: McpServer, client: DversumClient): void;
4
+ //# sourceMappingURL=absences.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"absences.d.ts","sourceRoot":"","sources":["../../../src/tools/absences.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,aAAa,QAwDtB"}
@@ -0,0 +1,44 @@
1
+ import { z } from "zod";
2
+ export function registerAbsenceTools(server, client) {
3
+ server.tool("list_absences", "List team absences (vacation, sick leave, home office, etc.).", {
4
+ start_date: z.string().optional().describe("Filter from date (YYYY-MM-DD)"),
5
+ end_date: z.string().optional().describe("Filter to date (YYYY-MM-DD)"),
6
+ type: z
7
+ .enum(["vacation", "sick", "absence", "homeoffice", "business_trip"])
8
+ .optional()
9
+ .describe("Filter by absence type"),
10
+ }, async ({ start_date, end_date, type }) => {
11
+ const params = {};
12
+ if (start_date)
13
+ params.start_date = start_date;
14
+ if (end_date)
15
+ params.end_date = end_date;
16
+ if (type)
17
+ params.type = type;
18
+ const data = await client.get("/absences", params);
19
+ return {
20
+ content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
21
+ };
22
+ });
23
+ server.tool("create_absence", "Create a new absence entry (vacation, sick leave, etc.).", {
24
+ type: z
25
+ .enum(["vacation", "sick", "absence", "homeoffice", "business_trip"])
26
+ .describe("Absence type"),
27
+ start_date: z.string().describe("Start date (YYYY-MM-DD)"),
28
+ end_date: z.string().describe("End date (YYYY-MM-DD)"),
29
+ note: z.string().optional().describe("Optional note"),
30
+ half_day: z.boolean().optional().describe("Whether this is a half-day absence"),
31
+ }, async (input) => {
32
+ const data = await client.post("/absences", input);
33
+ return {
34
+ content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
35
+ };
36
+ });
37
+ server.tool("get_vacation_stats", "Get vacation quota and usage statistics for the team.", {}, async () => {
38
+ const data = await client.get("/absences/stats");
39
+ return {
40
+ content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
41
+ };
42
+ });
43
+ }
44
+ //# sourceMappingURL=absences.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"absences.js","sourceRoot":"","sources":["../../../src/tools/absences.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,oBAAoB,CAClC,MAAiB,EACjB,MAAqB;IAErB,MAAM,CAAC,IAAI,CACT,eAAe,EACf,+DAA+D,EAC/D;QACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;QAC3E,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;QACvE,IAAI,EAAE,CAAC;aACJ,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,eAAe,CAAC,CAAC;aACpE,QAAQ,EAAE;aACV,QAAQ,CAAC,wBAAwB,CAAC;KACtC,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE;QACvC,MAAM,MAAM,GAA2B,EAAE,CAAC;QAC1C,IAAI,UAAU;YAAE,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;QAC/C,IAAI,QAAQ;YAAE,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzC,IAAI,IAAI;YAAE,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;QAC7B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACnD,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SACjE,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,0DAA0D,EAC1D;QACE,IAAI,EAAE,CAAC;aACJ,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,eAAe,CAAC,CAAC;aACpE,QAAQ,CAAC,cAAc,CAAC;QAC3B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;QAC1D,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QACtD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;QACrD,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;KAChF,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;QACd,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;QACnD,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SACjE,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,uDAAuD,EACvD,EAAE,EACF,KAAK,IAAI,EAAE;QACT,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QACjD,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SACjE,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { DversumClient } from "../client.js";
3
+ export declare function registerCalendarTools(server: McpServer, client: DversumClient): void;
4
+ //# sourceMappingURL=calendar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar.d.ts","sourceRoot":"","sources":["../../../src/tools/calendar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,aAAa,QA8FtB"}