@dain-os/mcp-server 0.1.0 → 0.1.1

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,127 +1,127 @@
1
- # @dain-os/mcp-server
2
-
3
- MCP server for DainOS. Lets Claude Code and other MCP clients manage your projects, tasks, and task comments through a small, well-scoped tool surface.
4
-
5
- ## What it does
6
-
7
- Wraps the DainOS Express API behind 12 tools:
8
-
9
- | Domain | Tools |
10
- |---|---|
11
- | Projects | `list_projects`, `get_project`, `create_project`, `update_project`, `archive_project` |
12
- | Tasks | `list_tasks`, `get_task`, `create_task`, `update_task`, `complete_task`, `archive_task` |
13
- | Comments | `add_task_comment` |
14
-
15
- All operations run as the user who minted the token. Tenant scoping is enforced server-side.
16
-
17
- ## Setup
18
-
19
- ### 1. Mint a personal access token
20
-
21
- Sign in to DainOS, go to **Settings -> API tokens**, click **New token**, give it a name (e.g. `claude-code-laptop`), and copy the value. The raw token is shown exactly once.
22
-
23
- Tokens look like `dain_pat_<43 base64url chars>`.
24
-
25
- ### 2. Add the server to your MCP client
26
-
27
- #### Claude Code
28
-
29
- ```bash
30
- claude mcp add dainos -- npx -y @dain-os/mcp-server
31
- ```
32
-
33
- Then set the token in your environment (or pass it inline):
34
-
35
- ```bash
36
- export DAINOS_API_TOKEN=dain_pat_<your token>
37
- ```
38
-
39
- Or, for one-machine setup, add it to your Claude Code config directly:
40
-
41
- ```json
42
- {
43
- "mcpServers": {
44
- "dainos": {
45
- "command": "npx",
46
- "args": ["-y", "@dain-os/mcp-server"],
47
- "env": {
48
- "DAINOS_API_TOKEN": "dain_pat_<your token>"
49
- }
50
- }
51
- }
52
- }
53
- ```
54
-
55
- ### 3. Restart your MCP client
56
-
57
- Claude Code picks up new MCP servers on restart.
58
-
59
- ## Environment
60
-
61
- | Variable | Required | Default | Notes |
62
- |---|---|---|---|
63
- | `DAINOS_API_TOKEN` | yes | n/a | Personal access token from `/settings/api-tokens` |
64
- | `DAINOS_API_URL` | no | `https://api.dainos.app` | Override for local dev or staging |
65
-
66
- ## Usage examples
67
-
68
- Once connected, ask Claude Code things like:
69
-
70
- - "List my active projects in DainOS."
71
- - "What tasks are assigned to me?"
72
- - "Create a task on the Portunus project called 'wire up the new sidebar' due Friday."
73
- - "Mark that task complete and add a comment that the PR is #312."
74
-
75
- The model uses `list_projects` to find ids, `create_task` / `update_task` / `complete_task` to mutate state, and `add_task_comment` for follow-ups.
76
-
77
- ## Troubleshooting
78
-
79
- ### 401 Unauthorized
80
-
81
- ```
82
- DainOS rejected the token (401). Mint a new one at https://dainos.app/settings/api-tokens
83
- ```
84
-
85
- The token is revoked, expired, or never existed. Visit Settings -> API tokens, mint a new one, and update your MCP config.
86
-
87
- ### 403 Forbidden
88
-
89
- The token is valid but your account does not have permission for the operation (e.g. archiving a project you do not own).
90
-
91
- ### Tool is not visible to Claude Code
92
-
93
- Restart Claude Code after `claude mcp add ...`. MCP servers are loaded once at startup.
94
-
95
- ## Local development
96
-
97
- ```bash
98
- git clone https://github.com/dain-agency/dain-os
99
- cd dain-os/packages/mcp-server
100
- npm install
101
- npm run build
102
- ```
103
-
104
- Then point your MCP client at the local build:
105
-
106
- ```json
107
- {
108
- "mcpServers": {
109
- "dainos-local": {
110
- "command": "node",
111
- "args": ["/path/to/dain-os/packages/mcp-server/dist/index.js"],
112
- "env": {
113
- "DAINOS_API_TOKEN": "dain_pat_...",
114
- "DAINOS_API_URL": "http://localhost:3001"
115
- }
116
- }
117
- }
118
- }
119
- ```
120
-
121
- ## Why a small tool surface
122
-
123
- The Notion MCP works well because it exposes a focused, opinionated set of operations rather than a one-to-one mirror of every API endpoint. The DainOS MCP server follows the same principle: project and task work covers the bulk of the day-to-day "keep things updated" use case, and the model picks the right verb every time. Tools for time entries, deals, proposals, and attachments are tracked for follow-up versions.
124
-
125
- ## Licence
126
-
127
- Proprietary. Internal use by Dain only.
1
+ # @dain-os/mcp-server
2
+
3
+ MCP server for DainOS. Lets Claude Code and other MCP clients manage your projects, tasks, and task comments through a small, well-scoped tool surface.
4
+
5
+ ## What it does
6
+
7
+ Wraps the DainOS Express API behind 12 tools:
8
+
9
+ | Domain | Tools |
10
+ |---|---|
11
+ | Projects | `list_projects`, `get_project`, `create_project`, `update_project`, `archive_project` |
12
+ | Tasks | `list_tasks`, `get_task`, `create_task`, `update_task`, `complete_task`, `archive_task` |
13
+ | Comments | `add_task_comment` |
14
+
15
+ All operations run as the user who minted the token. Tenant scoping is enforced server-side.
16
+
17
+ ## Setup
18
+
19
+ ### 1. Mint a personal access token
20
+
21
+ Sign in to DainOS, go to **Settings -> API tokens**, click **New token**, give it a name (e.g. `claude-code-laptop`), and copy the value. The raw token is shown exactly once.
22
+
23
+ Tokens look like `dain_pat_<43 base64url chars>`.
24
+
25
+ ### 2. Add the server to your MCP client
26
+
27
+ #### Claude Code
28
+
29
+ ```bash
30
+ claude mcp add dainos -- npx -y @dain-os/mcp-server
31
+ ```
32
+
33
+ Then set the token in your environment (or pass it inline):
34
+
35
+ ```bash
36
+ export DAINOS_API_TOKEN=dain_pat_<your token>
37
+ ```
38
+
39
+ Or, for one-machine setup, add it to your Claude Code config directly:
40
+
41
+ ```json
42
+ {
43
+ "mcpServers": {
44
+ "dainos": {
45
+ "command": "npx",
46
+ "args": ["-y", "@dain-os/mcp-server"],
47
+ "env": {
48
+ "DAINOS_API_TOKEN": "dain_pat_<your token>"
49
+ }
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ ### 3. Restart your MCP client
56
+
57
+ Claude Code picks up new MCP servers on restart.
58
+
59
+ ## Environment
60
+
61
+ | Variable | Required | Default | Notes |
62
+ |---|---|---|---|
63
+ | `DAINOS_API_TOKEN` | yes | n/a | Personal access token from `/settings/api-tokens` |
64
+ | `DAINOS_API_URL` | no | `https://api.dainos.app` | Override for local dev or staging |
65
+
66
+ ## Usage examples
67
+
68
+ Once connected, ask Claude Code things like:
69
+
70
+ - "List my active projects in DainOS."
71
+ - "What tasks are assigned to me?"
72
+ - "Create a task on the Portunus project called 'wire up the new sidebar' due Friday."
73
+ - "Mark that task complete and add a comment that the PR is #312."
74
+
75
+ The model uses `list_projects` to find ids, `create_task` / `update_task` / `complete_task` to mutate state, and `add_task_comment` for follow-ups.
76
+
77
+ ## Troubleshooting
78
+
79
+ ### 401 Unauthorized
80
+
81
+ ```
82
+ DainOS rejected the token (401). Mint a new one at https://dainos.app/settings/api-tokens
83
+ ```
84
+
85
+ The token is revoked, expired, or never existed. Visit Settings -> API tokens, mint a new one, and update your MCP config.
86
+
87
+ ### 403 Forbidden
88
+
89
+ The token is valid but your account does not have permission for the operation (e.g. archiving a project you do not own).
90
+
91
+ ### Tool is not visible to Claude Code
92
+
93
+ Restart Claude Code after `claude mcp add ...`. MCP servers are loaded once at startup.
94
+
95
+ ## Local development
96
+
97
+ ```bash
98
+ git clone https://github.com/dain-agency/dain-os
99
+ cd dain-os/packages/mcp-server
100
+ npm install
101
+ npm run build
102
+ ```
103
+
104
+ Then point your MCP client at the local build:
105
+
106
+ ```json
107
+ {
108
+ "mcpServers": {
109
+ "dainos-local": {
110
+ "command": "node",
111
+ "args": ["/path/to/dain-os/packages/mcp-server/dist/index.js"],
112
+ "env": {
113
+ "DAINOS_API_TOKEN": "dain_pat_...",
114
+ "DAINOS_API_URL": "http://localhost:3001"
115
+ }
116
+ }
117
+ }
118
+ }
119
+ ```
120
+
121
+ ## Why a small tool surface
122
+
123
+ The Notion MCP works well because it exposes a focused, opinionated set of operations rather than a one-to-one mirror of every API endpoint. The DainOS MCP server follows the same principle: project and task work covers the bulk of the day-to-day "keep things updated" use case, and the model picks the right verb every time. Tools for time entries, deals, proposals, and attachments are tracked for follow-up versions.
124
+
125
+ ## Licence
126
+
127
+ Proprietary. Internal use by Dain only.
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAM3D;AASD,qBAAa,YAAY;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM;IAKtD;;;;;OAKG;IACG,OAAO,CAAC,CAAC,EACb,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,EACnD,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,GACb,OAAO,CAAC,CAAC,CAAC;IAsCb,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAIhC,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,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;CAGpC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAWH,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;CAM3D;AASD,qBAAa,YAAY;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;gBAEX,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM;IAOtD;;;;;OAKG;IACG,OAAO,CAAC,CAAC,EACb,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,EACnD,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,GACb,OAAO,CAAC,CAAC,CAAC;IAmDb,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAIhC,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,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;CAGpC"}
package/dist/client.js CHANGED
@@ -11,6 +11,12 @@
11
11
  * tells the user exactly where to mint a new token.
12
12
  */
13
13
  const DEFAULT_API_URL = 'https://api.dainos.app';
14
+ /**
15
+ * Per-request timeout. If the API hangs we want the MCP server to surface a
16
+ * clear error to the model rather than block indefinitely with no feedback.
17
+ * 30s is generous for any of the operations we expose (single CRUD calls).
18
+ */
19
+ const REQUEST_TIMEOUT_MS = 30_000;
14
20
  export class DainOsApiError extends Error {
15
21
  status;
16
22
  body;
@@ -25,7 +31,9 @@ export class DainOsClient {
25
31
  baseUrl;
26
32
  token;
27
33
  constructor(baseUrl, token) {
28
- this.baseUrl = baseUrl ?? DEFAULT_API_URL;
34
+ // Strip trailing slashes so we never end up with `https://host//api/v1/...`,
35
+ // which some Express routers treat as a 404.
36
+ this.baseUrl = (baseUrl ?? DEFAULT_API_URL).replace(/\/+$/, '');
29
37
  this.token = token;
30
38
  }
31
39
  /**
@@ -43,11 +51,21 @@ export class DainOsClient {
43
51
  'Content-Type': 'application/json',
44
52
  Accept: 'application/json',
45
53
  },
54
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
46
55
  };
47
56
  if (body !== undefined) {
48
57
  init.body = JSON.stringify(body);
49
58
  }
50
- const response = await fetch(url, init);
59
+ let response;
60
+ try {
61
+ response = await fetch(url, init);
62
+ }
63
+ catch (error) {
64
+ if (error instanceof DOMException && error.name === 'TimeoutError') {
65
+ throw new DainOsApiError(0, '', `DainOS request timed out after ${REQUEST_TIMEOUT_MS / 1000}s. The API may be unreachable; check DAINOS_API_URL or your network.`);
66
+ }
67
+ throw error;
68
+ }
51
69
  if (response.status === 204) {
52
70
  return undefined;
53
71
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,20 @@ import { z } from 'zod';
10
10
  export function toJsonSchema(schema) {
11
11
  return zodToJsonSchema(schema);
12
12
  }
13
+ /**
14
+ * Pull a `.describe()` annotation off any Zod schema. Zod stores the string on
15
+ * `_def.description`, but the property isn't part of the public type for every
16
+ * wrapper kind, so we read it through a narrow cast.
17
+ */
18
+ function descriptionOf(schema) {
19
+ return schema._def.description;
20
+ }
21
+ function withDescription(schema, result) {
22
+ const description = descriptionOf(schema);
23
+ if (description && !result.description)
24
+ result.description = description;
25
+ return result;
26
+ }
13
27
  function zodToJsonSchema(schema) {
14
28
  if (schema instanceof z.ZodObject) {
15
29
  const shape = schema.shape;
@@ -27,40 +41,42 @@ function zodToJsonSchema(schema) {
27
41
  };
28
42
  if (required.length > 0)
29
43
  result.required = required;
30
- return result;
44
+ return withDescription(schema, result);
31
45
  }
32
46
  if (schema instanceof z.ZodOptional || schema instanceof z.ZodNullable) {
33
- return zodToJsonSchema(schema._def.innerType);
47
+ // Wrappers like `.optional().describe('...')` hold the description on the
48
+ // wrapper, not on the inner type. Forward it so the model sees the hint.
49
+ const inner = zodToJsonSchema(schema._def.innerType);
50
+ return withDescription(schema, inner);
34
51
  }
35
52
  if (schema instanceof z.ZodDefault) {
36
53
  const inner = zodToJsonSchema(schema._def.innerType);
37
54
  inner.default = schema._def.defaultValue();
38
- return inner;
55
+ return withDescription(schema, inner);
39
56
  }
40
57
  if (schema instanceof z.ZodString) {
41
- const result = { type: 'string' };
42
- const description = schema._def.description;
43
- if (description)
44
- result.description = description;
45
- return result;
58
+ return withDescription(schema, { type: 'string' });
46
59
  }
47
60
  if (schema instanceof z.ZodNumber) {
48
- return { type: 'number' };
61
+ return withDescription(schema, { type: 'number' });
49
62
  }
50
63
  if (schema instanceof z.ZodBoolean) {
51
- return { type: 'boolean' };
64
+ return withDescription(schema, { type: 'boolean' });
52
65
  }
53
66
  if (schema instanceof z.ZodEnum) {
54
- return { type: 'string', enum: [...schema._def.values] };
67
+ return withDescription(schema, { type: 'string', enum: [...schema._def.values] });
55
68
  }
56
69
  if (schema instanceof z.ZodArray) {
57
- return { type: 'array', items: zodToJsonSchema(schema._def.type) };
70
+ return withDescription(schema, {
71
+ type: 'array',
72
+ items: zodToJsonSchema(schema._def.type),
73
+ });
58
74
  }
59
75
  if (schema instanceof z.ZodLiteral) {
60
76
  const value = schema._def.value;
61
- return { type: typeof value, enum: [value] };
77
+ return withDescription(schema, { type: typeof value, enum: [value] });
62
78
  }
63
79
  // Fallback: permissive object. Should never hit in practice with our schemas.
64
- return { type: 'object' };
80
+ return withDescription(schema, { type: 'object' });
65
81
  }
66
82
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tools/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,34 +1,35 @@
1
- {
2
- "name": "@dain-os/mcp-server",
3
- "version": "0.1.0",
4
- "description": "MCP server for DainOS — manage projects and tasks from Claude Code and other MCP clients",
5
- "type": "module",
6
- "bin": {
7
- "dain-mcp": "./dist/index.js"
8
- },
9
- "main": "./dist/index.js",
10
- "types": "./dist/index.d.ts",
11
- "files": ["dist", "README.md"],
12
- "scripts": {
13
- "build": "tsc",
14
- "dev": "tsx watch src/index.ts",
15
- "test": "vitest run",
16
- "check-types": "tsc --noEmit"
17
- },
18
- "dependencies": {
19
- "@modelcontextprotocol/sdk": "^1.0.4",
20
- "zod": "^3.23.8"
21
- },
22
- "devDependencies": {
23
- "@types/node": "^20.11.0",
24
- "tsx": "^4.7.0",
25
- "typescript": "5.8.2",
26
- "vitest": "^1.6.0"
27
- },
28
- "engines": {
29
- "node": ">=18"
30
- },
31
- "publishConfig": {
32
- "access": "public"
33
- }
34
- }
1
+ {
2
+ "name": "@dain-os/mcp-server",
3
+ "version": "0.1.1",
4
+ "description": "MCP server for DainOS — manage projects and tasks from Claude Code and other MCP clients",
5
+ "type": "module",
6
+ "bin": {
7
+ "dain-mcp": "./dist/index.js",
8
+ "mcp-server": "./dist/index.js"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "files": ["dist", "README.md"],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "dev": "tsx watch src/index.ts",
16
+ "test": "vitest run",
17
+ "check-types": "tsc --noEmit"
18
+ },
19
+ "dependencies": {
20
+ "@modelcontextprotocol/sdk": "^1.0.4",
21
+ "zod": "^3.23.8"
22
+ },
23
+ "devDependencies": {
24
+ "@types/node": "^20.11.0",
25
+ "tsx": "^4.7.0",
26
+ "typescript": "5.8.2",
27
+ "vitest": "^1.6.0"
28
+ },
29
+ "engines": {
30
+ "node": ">=18"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ }
35
+ }