@starascendin/lifeos-mcp 0.1.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 +129 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +767 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# LifeOS MCP Server
|
|
2
|
+
|
|
3
|
+
MCP (Model Context Protocol) server for LifeOS Project Management. This allows AI assistants like Claude to interact with your LifeOS projects, tasks, cycles, notes, and contacts.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @starascendin/lifeos-mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or use directly with npx (no install needed):
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx @starascendin/lifeos-mcp --url <your-convex-url> --user-id <your-user-id> --api-key <your-api-key>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Configuration
|
|
18
|
+
|
|
19
|
+
### Required Parameters
|
|
20
|
+
|
|
21
|
+
| Parameter | CLI Flag | Env Variable | Description |
|
|
22
|
+
|-----------|----------|--------------|-------------|
|
|
23
|
+
| Convex URL | `--url`, `-u` | `CONVEX_URL` | Your Convex deployment URL (e.g., `https://your-app.convex.site`) |
|
|
24
|
+
| User ID | `--user-id`, `-i` | `LIFEOS_USER_ID` | Your LifeOS user ID |
|
|
25
|
+
| API Key | `--api-key`, `-k` | `LIFEOS_API_KEY` | Your API key for authentication |
|
|
26
|
+
|
|
27
|
+
### Getting Your Credentials
|
|
28
|
+
|
|
29
|
+
1. **Convex URL**: Find in your Convex dashboard - use the `.convex.site` URL (not `.convex.cloud`)
|
|
30
|
+
2. **User ID**: In LifeOS app, go to Settings > Developer, or query from Convex Dashboard
|
|
31
|
+
3. **API Key**: Generate from your LifeOS settings or Convex dashboard
|
|
32
|
+
|
|
33
|
+
## Usage with Claude Code
|
|
34
|
+
|
|
35
|
+
Add to your `.mcp.json` (project root or `~/.claude/mcp.json`):
|
|
36
|
+
|
|
37
|
+
### Using CLI flags:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"mcpServers": {
|
|
42
|
+
"lifeos": {
|
|
43
|
+
"command": "npx",
|
|
44
|
+
"args": [
|
|
45
|
+
"@starascendin/lifeos-mcp",
|
|
46
|
+
"--url", "https://your-app.convex.site",
|
|
47
|
+
"--user-id", "your-user-id",
|
|
48
|
+
"--api-key", "your-api-key"
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Using environment variables:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"mcpServers": {
|
|
60
|
+
"lifeos": {
|
|
61
|
+
"command": "npx",
|
|
62
|
+
"args": ["@starascendin/lifeos-mcp"],
|
|
63
|
+
"env": {
|
|
64
|
+
"CONVEX_URL": "https://your-app.convex.site",
|
|
65
|
+
"LIFEOS_USER_ID": "your-user-id",
|
|
66
|
+
"LIFEOS_API_KEY": "your-api-key"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Available Tools
|
|
74
|
+
|
|
75
|
+
### Project Management
|
|
76
|
+
- **get_projects** - List all projects with stats
|
|
77
|
+
- **get_tasks** - Get tasks with filters (project, status, priority)
|
|
78
|
+
- **get_todays_tasks** - Get today's tasks and top priorities
|
|
79
|
+
- **create_issue** - Create a new task/issue
|
|
80
|
+
- **mark_issue_complete** - Mark a task as done
|
|
81
|
+
|
|
82
|
+
### Phases
|
|
83
|
+
- **get_phases** - Get all phases for a project
|
|
84
|
+
- **get_phase** - Get phase details with issues
|
|
85
|
+
- **create_phase** - Create a new phase
|
|
86
|
+
- **update_phase** - Update phase details
|
|
87
|
+
- **delete_phase** - Delete a phase
|
|
88
|
+
- **assign_issue_to_phase** - Assign/unassign issue to phase
|
|
89
|
+
|
|
90
|
+
### Cycles/Sprints
|
|
91
|
+
- **get_current_cycle** - Get active cycle with progress
|
|
92
|
+
- **assign_issue_to_cycle** - Add task to a cycle
|
|
93
|
+
|
|
94
|
+
### Agenda
|
|
95
|
+
- **get_daily_agenda** - Today's tasks, events, priorities
|
|
96
|
+
- **get_weekly_agenda** - Week's tasks and events
|
|
97
|
+
|
|
98
|
+
### Notes
|
|
99
|
+
- **search_notes** - Search voice memos/notes
|
|
100
|
+
- **get_recent_notes** - Get recent notes
|
|
101
|
+
- **create_quick_note** - Create a text note
|
|
102
|
+
- **add_tags_to_note** - Tag a note
|
|
103
|
+
|
|
104
|
+
### People/Contacts
|
|
105
|
+
- **get_people** - List all contacts
|
|
106
|
+
- **get_person** - Get person details with AI profile
|
|
107
|
+
- **search_people** - Search contacts by name
|
|
108
|
+
- **create_person** - Create a new contact
|
|
109
|
+
- **update_person** - Update contact details
|
|
110
|
+
- **get_memos_for_person** - Get voice memos linked to a person
|
|
111
|
+
- **get_person_timeline** - Get interaction timeline
|
|
112
|
+
- **link_memo_to_person** - Link a memo to a person
|
|
113
|
+
|
|
114
|
+
### Clients
|
|
115
|
+
- **get_clients** - List all clients
|
|
116
|
+
- **get_client** - Get client details
|
|
117
|
+
- **get_projects_for_client** - Get client's projects
|
|
118
|
+
- **create_client** - Create a new client
|
|
119
|
+
- **update_client** - Update client details
|
|
120
|
+
|
|
121
|
+
## CLI Help
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
lifeos-mcp --help
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## License
|
|
128
|
+
|
|
129
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* LifeOS MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Exposes LifeOS Project Management tools via Model Context Protocol.
|
|
6
|
+
* Calls the Convex HTTP /tool-call endpoint.
|
|
7
|
+
*
|
|
8
|
+
* CLI flags (take precedence over env vars):
|
|
9
|
+
* --url, -u Convex deployment URL (e.g., https://your-deployment.convex.site)
|
|
10
|
+
* --user-id, -i User ID for API authentication
|
|
11
|
+
* --api-key, -k API key for authentication
|
|
12
|
+
*
|
|
13
|
+
* Environment variables (fallback):
|
|
14
|
+
* CONVEX_URL Convex deployment URL
|
|
15
|
+
* LIFEOS_USER_ID User ID for API key auth
|
|
16
|
+
* LIFEOS_API_KEY API key for authentication
|
|
17
|
+
*/
|
|
18
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,767 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* LifeOS MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Exposes LifeOS Project Management tools via Model Context Protocol.
|
|
6
|
+
* Calls the Convex HTTP /tool-call endpoint.
|
|
7
|
+
*
|
|
8
|
+
* CLI flags (take precedence over env vars):
|
|
9
|
+
* --url, -u Convex deployment URL (e.g., https://your-deployment.convex.site)
|
|
10
|
+
* --user-id, -i User ID for API authentication
|
|
11
|
+
* --api-key, -k API key for authentication
|
|
12
|
+
*
|
|
13
|
+
* Environment variables (fallback):
|
|
14
|
+
* CONVEX_URL Convex deployment URL
|
|
15
|
+
* LIFEOS_USER_ID User ID for API key auth
|
|
16
|
+
* LIFEOS_API_KEY API key for authentication
|
|
17
|
+
*/
|
|
18
|
+
import { Command } from "commander";
|
|
19
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
20
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
21
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
22
|
+
// Parse CLI arguments
|
|
23
|
+
const program = new Command();
|
|
24
|
+
program
|
|
25
|
+
.name("lifeos-mcp")
|
|
26
|
+
.description("MCP server for LifeOS Project Management")
|
|
27
|
+
.version("0.1.0")
|
|
28
|
+
.option("-u, --url <url>", "Convex deployment URL")
|
|
29
|
+
.option("-i, --user-id <id>", "User ID for API authentication")
|
|
30
|
+
.option("-k, --api-key <key>", "API key for authentication")
|
|
31
|
+
.parse();
|
|
32
|
+
const options = program.opts();
|
|
33
|
+
// Tool definitions matching the Convex tool-call endpoint
|
|
34
|
+
const TOOLS = [
|
|
35
|
+
// Project Management Tools
|
|
36
|
+
{
|
|
37
|
+
name: "get_projects",
|
|
38
|
+
description: "Get user's projects with issue counts and completion stats. Use this to see all projects and their status.",
|
|
39
|
+
inputSchema: {
|
|
40
|
+
type: "object",
|
|
41
|
+
properties: {
|
|
42
|
+
status: {
|
|
43
|
+
type: "string",
|
|
44
|
+
enum: ["planned", "in_progress", "paused", "completed", "cancelled"],
|
|
45
|
+
description: "Filter by project status",
|
|
46
|
+
},
|
|
47
|
+
includeArchived: {
|
|
48
|
+
type: "boolean",
|
|
49
|
+
description: "Include archived projects (default: false)",
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: "get_tasks",
|
|
56
|
+
description: "Get tasks/issues with optional filters. Use this to list tasks in a project or by status/priority.",
|
|
57
|
+
inputSchema: {
|
|
58
|
+
type: "object",
|
|
59
|
+
properties: {
|
|
60
|
+
projectId: {
|
|
61
|
+
type: "string",
|
|
62
|
+
description: "Filter by project ID",
|
|
63
|
+
},
|
|
64
|
+
status: {
|
|
65
|
+
type: "string",
|
|
66
|
+
enum: [
|
|
67
|
+
"backlog",
|
|
68
|
+
"todo",
|
|
69
|
+
"in_progress",
|
|
70
|
+
"in_review",
|
|
71
|
+
"done",
|
|
72
|
+
"cancelled",
|
|
73
|
+
],
|
|
74
|
+
description: "Filter by task status",
|
|
75
|
+
},
|
|
76
|
+
priority: {
|
|
77
|
+
type: "string",
|
|
78
|
+
enum: ["urgent", "high", "medium", "low", "none"],
|
|
79
|
+
description: "Filter by priority level",
|
|
80
|
+
},
|
|
81
|
+
limit: {
|
|
82
|
+
type: "number",
|
|
83
|
+
description: "Max results (default 50, max 100)",
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "get_todays_tasks",
|
|
90
|
+
description: "Get today's tasks including tasks due today and top priority items. Best for daily planning.",
|
|
91
|
+
inputSchema: {
|
|
92
|
+
type: "object",
|
|
93
|
+
properties: {},
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "create_issue",
|
|
98
|
+
description: "Create a new task/issue. Optionally assign to a project, set priority, and due date.",
|
|
99
|
+
inputSchema: {
|
|
100
|
+
type: "object",
|
|
101
|
+
properties: {
|
|
102
|
+
title: {
|
|
103
|
+
type: "string",
|
|
104
|
+
description: "The task title (required)",
|
|
105
|
+
},
|
|
106
|
+
description: {
|
|
107
|
+
type: "string",
|
|
108
|
+
description: "Detailed description (optional)",
|
|
109
|
+
},
|
|
110
|
+
projectIdOrKey: {
|
|
111
|
+
type: "string",
|
|
112
|
+
description: "Project ID or key like 'ACME' (optional)",
|
|
113
|
+
},
|
|
114
|
+
priority: {
|
|
115
|
+
type: "string",
|
|
116
|
+
enum: ["urgent", "high", "medium", "low", "none"],
|
|
117
|
+
description: "Priority level (optional, default: none)",
|
|
118
|
+
},
|
|
119
|
+
dueDate: {
|
|
120
|
+
type: "string",
|
|
121
|
+
description: "Due date in ISO format like '2024-01-15' (optional)",
|
|
122
|
+
},
|
|
123
|
+
cycleId: {
|
|
124
|
+
type: "string",
|
|
125
|
+
description: "Assign to a specific cycle (optional)",
|
|
126
|
+
},
|
|
127
|
+
phaseId: {
|
|
128
|
+
type: "string",
|
|
129
|
+
description: "Assign to a specific phase within the project (optional)",
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
required: ["title"],
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
name: "mark_issue_complete",
|
|
137
|
+
description: "Mark a task as complete. Accepts issue ID or identifier like 'PROJ-123'.",
|
|
138
|
+
inputSchema: {
|
|
139
|
+
type: "object",
|
|
140
|
+
properties: {
|
|
141
|
+
issueIdOrIdentifier: {
|
|
142
|
+
type: "string",
|
|
143
|
+
description: "Issue ID or identifier like PROJ-123 (required)",
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
required: ["issueIdOrIdentifier"],
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
// Cycle/Sprint Tools
|
|
150
|
+
{
|
|
151
|
+
name: "get_current_cycle",
|
|
152
|
+
description: "Get the currently active cycle/sprint with progress stats and top priority issues.",
|
|
153
|
+
inputSchema: {
|
|
154
|
+
type: "object",
|
|
155
|
+
properties: {},
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: "assign_issue_to_cycle",
|
|
160
|
+
description: "Assign a task to a cycle. Defaults to current active cycle if no cycleId provided.",
|
|
161
|
+
inputSchema: {
|
|
162
|
+
type: "object",
|
|
163
|
+
properties: {
|
|
164
|
+
issueIdOrIdentifier: {
|
|
165
|
+
type: "string",
|
|
166
|
+
description: "Issue ID or identifier like PROJ-123 (required)",
|
|
167
|
+
},
|
|
168
|
+
cycleId: {
|
|
169
|
+
type: "string",
|
|
170
|
+
description: "Cycle ID (optional, defaults to active cycle)",
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
required: ["issueIdOrIdentifier"],
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
// Agenda Tools
|
|
177
|
+
{
|
|
178
|
+
name: "get_daily_agenda",
|
|
179
|
+
description: "Get today's full agenda: tasks due today, calendar events, and top priorities.",
|
|
180
|
+
inputSchema: {
|
|
181
|
+
type: "object",
|
|
182
|
+
properties: {
|
|
183
|
+
date: {
|
|
184
|
+
type: "string",
|
|
185
|
+
description: "Specific date in ISO format (optional, default: today)",
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
name: "get_weekly_agenda",
|
|
192
|
+
description: "Get weekly agenda: tasks and events for the next 7 days, plus AI weekly summary.",
|
|
193
|
+
inputSchema: {
|
|
194
|
+
type: "object",
|
|
195
|
+
properties: {
|
|
196
|
+
startDate: {
|
|
197
|
+
type: "string",
|
|
198
|
+
description: "Start date in ISO format (optional, default: today)",
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
// Notes Tools
|
|
204
|
+
{
|
|
205
|
+
name: "search_notes",
|
|
206
|
+
description: "Search voice memos/notes by content.",
|
|
207
|
+
inputSchema: {
|
|
208
|
+
type: "object",
|
|
209
|
+
properties: {
|
|
210
|
+
query: {
|
|
211
|
+
type: "string",
|
|
212
|
+
description: "Search terms to find in notes (required)",
|
|
213
|
+
},
|
|
214
|
+
limit: {
|
|
215
|
+
type: "number",
|
|
216
|
+
description: "Max results (default 10, max 50)",
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
required: ["query"],
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
name: "get_recent_notes",
|
|
224
|
+
description: "Get recent voice memos/notes with transcripts.",
|
|
225
|
+
inputSchema: {
|
|
226
|
+
type: "object",
|
|
227
|
+
properties: {
|
|
228
|
+
limit: {
|
|
229
|
+
type: "number",
|
|
230
|
+
description: "Number of notes to return (default 5, max 20)",
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
name: "create_quick_note",
|
|
237
|
+
description: "Create a quick text note. Useful for capturing thoughts.",
|
|
238
|
+
inputSchema: {
|
|
239
|
+
type: "object",
|
|
240
|
+
properties: {
|
|
241
|
+
content: {
|
|
242
|
+
type: "string",
|
|
243
|
+
description: "The note content (required)",
|
|
244
|
+
},
|
|
245
|
+
tags: {
|
|
246
|
+
type: "array",
|
|
247
|
+
items: { type: "string" },
|
|
248
|
+
description: "Tags for categorization (optional)",
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
required: ["content"],
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
name: "add_tags_to_note",
|
|
256
|
+
description: "Add tags to an existing note.",
|
|
257
|
+
inputSchema: {
|
|
258
|
+
type: "object",
|
|
259
|
+
properties: {
|
|
260
|
+
noteId: {
|
|
261
|
+
type: "string",
|
|
262
|
+
description: "The note ID (required)",
|
|
263
|
+
},
|
|
264
|
+
tags: {
|
|
265
|
+
type: "array",
|
|
266
|
+
items: { type: "string" },
|
|
267
|
+
description: "Tags to add (required)",
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
required: ["noteId", "tags"],
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
// FRM (Friend Relationship Management) Tools
|
|
274
|
+
{
|
|
275
|
+
name: "get_people",
|
|
276
|
+
description: "Get all contacts/people with optional filters. Use this to list all your contacts.",
|
|
277
|
+
inputSchema: {
|
|
278
|
+
type: "object",
|
|
279
|
+
properties: {
|
|
280
|
+
relationshipType: {
|
|
281
|
+
type: "string",
|
|
282
|
+
enum: ["family", "friend", "colleague", "acquaintance", "mentor", "other"],
|
|
283
|
+
description: "Filter by relationship type",
|
|
284
|
+
},
|
|
285
|
+
includeArchived: {
|
|
286
|
+
type: "boolean",
|
|
287
|
+
description: "Include archived people (default: false)",
|
|
288
|
+
},
|
|
289
|
+
limit: {
|
|
290
|
+
type: "number",
|
|
291
|
+
description: "Max results (default 100)",
|
|
292
|
+
},
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
name: "get_person",
|
|
298
|
+
description: "Get a single person's details with their AI-generated profile including communication style, personality insights, and relationship tips.",
|
|
299
|
+
inputSchema: {
|
|
300
|
+
type: "object",
|
|
301
|
+
properties: {
|
|
302
|
+
personId: {
|
|
303
|
+
type: "string",
|
|
304
|
+
description: "The person's ID (required)",
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
required: ["personId"],
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
name: "search_people",
|
|
312
|
+
description: "Search contacts by name using full-text search.",
|
|
313
|
+
inputSchema: {
|
|
314
|
+
type: "object",
|
|
315
|
+
properties: {
|
|
316
|
+
query: {
|
|
317
|
+
type: "string",
|
|
318
|
+
description: "Search terms to find in names (required)",
|
|
319
|
+
},
|
|
320
|
+
limit: {
|
|
321
|
+
type: "number",
|
|
322
|
+
description: "Max results (default 20)",
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
required: ["query"],
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
name: "get_memos_for_person",
|
|
330
|
+
description: "Get all voice memos linked to a specific person. Shows the transcripts and context for each memo.",
|
|
331
|
+
inputSchema: {
|
|
332
|
+
type: "object",
|
|
333
|
+
properties: {
|
|
334
|
+
personId: {
|
|
335
|
+
type: "string",
|
|
336
|
+
description: "The person's ID (required)",
|
|
337
|
+
},
|
|
338
|
+
limit: {
|
|
339
|
+
type: "number",
|
|
340
|
+
description: "Max results (default 50)",
|
|
341
|
+
},
|
|
342
|
+
},
|
|
343
|
+
required: ["personId"],
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
name: "get_person_timeline",
|
|
348
|
+
description: "Get interaction timeline for a person or all people. Shows voice memos and notes chronologically.",
|
|
349
|
+
inputSchema: {
|
|
350
|
+
type: "object",
|
|
351
|
+
properties: {
|
|
352
|
+
personId: {
|
|
353
|
+
type: "string",
|
|
354
|
+
description: "Filter to specific person (omit for all)",
|
|
355
|
+
},
|
|
356
|
+
limit: {
|
|
357
|
+
type: "number",
|
|
358
|
+
description: "Max results (default 50)",
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
name: "create_person",
|
|
365
|
+
description: "Create a new contact/person.",
|
|
366
|
+
inputSchema: {
|
|
367
|
+
type: "object",
|
|
368
|
+
properties: {
|
|
369
|
+
name: {
|
|
370
|
+
type: "string",
|
|
371
|
+
description: "The person's name (required)",
|
|
372
|
+
},
|
|
373
|
+
nickname: {
|
|
374
|
+
type: "string",
|
|
375
|
+
description: "Nickname or alias (optional)",
|
|
376
|
+
},
|
|
377
|
+
relationshipType: {
|
|
378
|
+
type: "string",
|
|
379
|
+
enum: ["family", "friend", "colleague", "acquaintance", "mentor", "other"],
|
|
380
|
+
description: "Relationship type (optional)",
|
|
381
|
+
},
|
|
382
|
+
avatarEmoji: {
|
|
383
|
+
type: "string",
|
|
384
|
+
description: "Emoji to represent this person (optional)",
|
|
385
|
+
},
|
|
386
|
+
notes: {
|
|
387
|
+
type: "string",
|
|
388
|
+
description: "User notes about this person (optional)",
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
required: ["name"],
|
|
392
|
+
},
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
name: "update_person",
|
|
396
|
+
description: "Update a contact's details.",
|
|
397
|
+
inputSchema: {
|
|
398
|
+
type: "object",
|
|
399
|
+
properties: {
|
|
400
|
+
personId: {
|
|
401
|
+
type: "string",
|
|
402
|
+
description: "The person's ID (required)",
|
|
403
|
+
},
|
|
404
|
+
name: {
|
|
405
|
+
type: "string",
|
|
406
|
+
description: "Updated name (optional)",
|
|
407
|
+
},
|
|
408
|
+
nickname: {
|
|
409
|
+
type: "string",
|
|
410
|
+
description: "Updated nickname (optional)",
|
|
411
|
+
},
|
|
412
|
+
relationshipType: {
|
|
413
|
+
type: "string",
|
|
414
|
+
enum: ["family", "friend", "colleague", "acquaintance", "mentor", "other"],
|
|
415
|
+
description: "Updated relationship type (optional)",
|
|
416
|
+
},
|
|
417
|
+
email: {
|
|
418
|
+
type: "string",
|
|
419
|
+
description: "Email address (optional)",
|
|
420
|
+
},
|
|
421
|
+
phone: {
|
|
422
|
+
type: "string",
|
|
423
|
+
description: "Phone number (optional)",
|
|
424
|
+
},
|
|
425
|
+
notes: {
|
|
426
|
+
type: "string",
|
|
427
|
+
description: "Updated notes (optional)",
|
|
428
|
+
},
|
|
429
|
+
},
|
|
430
|
+
required: ["personId"],
|
|
431
|
+
},
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
name: "link_memo_to_person",
|
|
435
|
+
description: "Link a voice memo to a person.",
|
|
436
|
+
inputSchema: {
|
|
437
|
+
type: "object",
|
|
438
|
+
properties: {
|
|
439
|
+
personId: {
|
|
440
|
+
type: "string",
|
|
441
|
+
description: "The person's ID (required)",
|
|
442
|
+
},
|
|
443
|
+
voiceMemoId: {
|
|
444
|
+
type: "string",
|
|
445
|
+
description: "The voice memo's ID (required)",
|
|
446
|
+
},
|
|
447
|
+
context: {
|
|
448
|
+
type: "string",
|
|
449
|
+
description: "Context for the link, e.g., 'Phone call', 'Coffee meetup' (optional)",
|
|
450
|
+
},
|
|
451
|
+
},
|
|
452
|
+
required: ["personId", "voiceMemoId"],
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
// Client Management Tools
|
|
456
|
+
{
|
|
457
|
+
name: "get_clients",
|
|
458
|
+
description: "Get all clients for consulting/freelance work with optional status filter.",
|
|
459
|
+
inputSchema: {
|
|
460
|
+
type: "object",
|
|
461
|
+
properties: {
|
|
462
|
+
status: {
|
|
463
|
+
type: "string",
|
|
464
|
+
enum: ["active", "archived"],
|
|
465
|
+
description: "Filter by status (optional)",
|
|
466
|
+
},
|
|
467
|
+
},
|
|
468
|
+
},
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
name: "get_client",
|
|
472
|
+
description: "Get a single client's details with project statistics.",
|
|
473
|
+
inputSchema: {
|
|
474
|
+
type: "object",
|
|
475
|
+
properties: {
|
|
476
|
+
clientId: {
|
|
477
|
+
type: "string",
|
|
478
|
+
description: "The client's ID (required)",
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
required: ["clientId"],
|
|
482
|
+
},
|
|
483
|
+
},
|
|
484
|
+
{
|
|
485
|
+
name: "get_projects_for_client",
|
|
486
|
+
description: "Get all projects associated with a client, including completion stats.",
|
|
487
|
+
inputSchema: {
|
|
488
|
+
type: "object",
|
|
489
|
+
properties: {
|
|
490
|
+
clientId: {
|
|
491
|
+
type: "string",
|
|
492
|
+
description: "The client's ID (required)",
|
|
493
|
+
},
|
|
494
|
+
},
|
|
495
|
+
required: ["clientId"],
|
|
496
|
+
},
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
name: "create_client",
|
|
500
|
+
description: "Create a new client for consulting/freelance work.",
|
|
501
|
+
inputSchema: {
|
|
502
|
+
type: "object",
|
|
503
|
+
properties: {
|
|
504
|
+
name: {
|
|
505
|
+
type: "string",
|
|
506
|
+
description: "The client's name (required)",
|
|
507
|
+
},
|
|
508
|
+
description: {
|
|
509
|
+
type: "string",
|
|
510
|
+
description: "Description of the client (optional)",
|
|
511
|
+
},
|
|
512
|
+
},
|
|
513
|
+
required: ["name"],
|
|
514
|
+
},
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
name: "update_client",
|
|
518
|
+
description: "Update a client's details.",
|
|
519
|
+
inputSchema: {
|
|
520
|
+
type: "object",
|
|
521
|
+
properties: {
|
|
522
|
+
clientId: {
|
|
523
|
+
type: "string",
|
|
524
|
+
description: "The client's ID (required)",
|
|
525
|
+
},
|
|
526
|
+
name: {
|
|
527
|
+
type: "string",
|
|
528
|
+
description: "Updated name (optional)",
|
|
529
|
+
},
|
|
530
|
+
description: {
|
|
531
|
+
type: "string",
|
|
532
|
+
description: "Updated description (optional)",
|
|
533
|
+
},
|
|
534
|
+
status: {
|
|
535
|
+
type: "string",
|
|
536
|
+
enum: ["active", "archived"],
|
|
537
|
+
description: "Updated status (optional)",
|
|
538
|
+
},
|
|
539
|
+
},
|
|
540
|
+
required: ["clientId"],
|
|
541
|
+
},
|
|
542
|
+
},
|
|
543
|
+
// Phase Management Tools
|
|
544
|
+
{
|
|
545
|
+
name: "get_phases",
|
|
546
|
+
description: "Get all phases for a project with issue stats. Use this to see project breakdown by phases.",
|
|
547
|
+
inputSchema: {
|
|
548
|
+
type: "object",
|
|
549
|
+
properties: {
|
|
550
|
+
projectId: {
|
|
551
|
+
type: "string",
|
|
552
|
+
description: "The project's ID (required)",
|
|
553
|
+
},
|
|
554
|
+
},
|
|
555
|
+
required: ["projectId"],
|
|
556
|
+
},
|
|
557
|
+
},
|
|
558
|
+
{
|
|
559
|
+
name: "get_phase",
|
|
560
|
+
description: "Get a single phase with its issues. Use this to see phase details and issues assigned to it.",
|
|
561
|
+
inputSchema: {
|
|
562
|
+
type: "object",
|
|
563
|
+
properties: {
|
|
564
|
+
phaseId: {
|
|
565
|
+
type: "string",
|
|
566
|
+
description: "The phase's ID (required)",
|
|
567
|
+
},
|
|
568
|
+
},
|
|
569
|
+
required: ["phaseId"],
|
|
570
|
+
},
|
|
571
|
+
},
|
|
572
|
+
{
|
|
573
|
+
name: "create_phase",
|
|
574
|
+
description: "Create a new phase in a project. Use this to organize project work into distinct stages.",
|
|
575
|
+
inputSchema: {
|
|
576
|
+
type: "object",
|
|
577
|
+
properties: {
|
|
578
|
+
projectId: {
|
|
579
|
+
type: "string",
|
|
580
|
+
description: "The project's ID (required)",
|
|
581
|
+
},
|
|
582
|
+
name: {
|
|
583
|
+
type: "string",
|
|
584
|
+
description: "The phase name (required)",
|
|
585
|
+
},
|
|
586
|
+
description: {
|
|
587
|
+
type: "string",
|
|
588
|
+
description: "Phase description, markdown supported (optional)",
|
|
589
|
+
},
|
|
590
|
+
status: {
|
|
591
|
+
type: "string",
|
|
592
|
+
enum: ["not_started", "in_progress", "completed"],
|
|
593
|
+
description: "Phase status (optional, default: not_started)",
|
|
594
|
+
},
|
|
595
|
+
},
|
|
596
|
+
required: ["projectId", "name"],
|
|
597
|
+
},
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
name: "update_phase",
|
|
601
|
+
description: "Update a phase's details.",
|
|
602
|
+
inputSchema: {
|
|
603
|
+
type: "object",
|
|
604
|
+
properties: {
|
|
605
|
+
phaseId: {
|
|
606
|
+
type: "string",
|
|
607
|
+
description: "The phase's ID (required)",
|
|
608
|
+
},
|
|
609
|
+
name: {
|
|
610
|
+
type: "string",
|
|
611
|
+
description: "Updated name (optional)",
|
|
612
|
+
},
|
|
613
|
+
description: {
|
|
614
|
+
type: "string",
|
|
615
|
+
description: "Updated description (optional)",
|
|
616
|
+
},
|
|
617
|
+
status: {
|
|
618
|
+
type: "string",
|
|
619
|
+
enum: ["not_started", "in_progress", "completed"],
|
|
620
|
+
description: "Updated status (optional)",
|
|
621
|
+
},
|
|
622
|
+
startDate: {
|
|
623
|
+
type: "string",
|
|
624
|
+
description: "Start date in ISO format (optional)",
|
|
625
|
+
},
|
|
626
|
+
endDate: {
|
|
627
|
+
type: "string",
|
|
628
|
+
description: "End date in ISO format (optional)",
|
|
629
|
+
},
|
|
630
|
+
},
|
|
631
|
+
required: ["phaseId"],
|
|
632
|
+
},
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
name: "delete_phase",
|
|
636
|
+
description: "Delete a phase. Issues in the phase are unlinked (not deleted).",
|
|
637
|
+
inputSchema: {
|
|
638
|
+
type: "object",
|
|
639
|
+
properties: {
|
|
640
|
+
phaseId: {
|
|
641
|
+
type: "string",
|
|
642
|
+
description: "The phase's ID (required)",
|
|
643
|
+
},
|
|
644
|
+
},
|
|
645
|
+
required: ["phaseId"],
|
|
646
|
+
},
|
|
647
|
+
},
|
|
648
|
+
{
|
|
649
|
+
name: "assign_issue_to_phase",
|
|
650
|
+
description: "Assign an issue to a phase, or unassign by omitting phaseId.",
|
|
651
|
+
inputSchema: {
|
|
652
|
+
type: "object",
|
|
653
|
+
properties: {
|
|
654
|
+
issueIdOrIdentifier: {
|
|
655
|
+
type: "string",
|
|
656
|
+
description: "Issue ID or identifier like PROJ-123 (required)",
|
|
657
|
+
},
|
|
658
|
+
phaseId: {
|
|
659
|
+
type: "string",
|
|
660
|
+
description: "Phase ID (optional - omit to unassign from current phase)",
|
|
661
|
+
},
|
|
662
|
+
},
|
|
663
|
+
required: ["issueIdOrIdentifier"],
|
|
664
|
+
},
|
|
665
|
+
},
|
|
666
|
+
];
|
|
667
|
+
// Configuration: CLI flags take precedence over env vars
|
|
668
|
+
// NOTE: HTTP routes are served from .convex.site, NOT .convex.cloud
|
|
669
|
+
const CONVEX_URL = options.url || process.env.CONVEX_URL;
|
|
670
|
+
const API_KEY = options.apiKey || process.env.LIFEOS_API_KEY;
|
|
671
|
+
const USER_ID = options.userId || process.env.LIFEOS_USER_ID;
|
|
672
|
+
// Validate required configuration
|
|
673
|
+
const missingConfig = [];
|
|
674
|
+
if (!CONVEX_URL)
|
|
675
|
+
missingConfig.push("CONVEX_URL (--url or CONVEX_URL env)");
|
|
676
|
+
if (!API_KEY)
|
|
677
|
+
missingConfig.push("API_KEY (--api-key or LIFEOS_API_KEY env)");
|
|
678
|
+
if (!USER_ID)
|
|
679
|
+
missingConfig.push("USER_ID (--user-id or LIFEOS_USER_ID env)");
|
|
680
|
+
if (missingConfig.length > 0) {
|
|
681
|
+
console.error("Error: Missing required configuration:");
|
|
682
|
+
missingConfig.forEach((c) => console.error(` - ${c}`));
|
|
683
|
+
console.error("");
|
|
684
|
+
console.error("Example usage:");
|
|
685
|
+
console.error(" lifeos-mcp --url https://your-app.convex.site --user-id xxx --api-key yyy");
|
|
686
|
+
console.error("");
|
|
687
|
+
console.error("Or with environment variables:");
|
|
688
|
+
console.error(" CONVEX_URL=https://your-app.convex.site LIFEOS_USER_ID=xxx LIFEOS_API_KEY=yyy lifeos-mcp");
|
|
689
|
+
process.exit(1);
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Call the Convex /tool-call HTTP endpoint
|
|
693
|
+
*/
|
|
694
|
+
async function callConvexTool(tool, params) {
|
|
695
|
+
const url = `${CONVEX_URL}/tool-call`;
|
|
696
|
+
const response = await fetch(url, {
|
|
697
|
+
method: "POST",
|
|
698
|
+
headers: {
|
|
699
|
+
"Content-Type": "application/json",
|
|
700
|
+
"X-API-Key": API_KEY,
|
|
701
|
+
},
|
|
702
|
+
body: JSON.stringify({
|
|
703
|
+
tool,
|
|
704
|
+
userId: USER_ID,
|
|
705
|
+
params,
|
|
706
|
+
}),
|
|
707
|
+
});
|
|
708
|
+
if (!response.ok) {
|
|
709
|
+
const errorText = await response.text();
|
|
710
|
+
throw new Error(`Convex API error (${response.status}): ${errorText}`);
|
|
711
|
+
}
|
|
712
|
+
const result = await response.json();
|
|
713
|
+
if (!result.success && result.error) {
|
|
714
|
+
throw new Error(result.error);
|
|
715
|
+
}
|
|
716
|
+
return result.result;
|
|
717
|
+
}
|
|
718
|
+
// Create the MCP server
|
|
719
|
+
const server = new Server({
|
|
720
|
+
name: "lifeos-pm",
|
|
721
|
+
version: "0.1.0",
|
|
722
|
+
}, {
|
|
723
|
+
capabilities: {
|
|
724
|
+
tools: {},
|
|
725
|
+
},
|
|
726
|
+
});
|
|
727
|
+
// Handle list tools request
|
|
728
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
729
|
+
return { tools: TOOLS };
|
|
730
|
+
});
|
|
731
|
+
// Handle tool calls
|
|
732
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
733
|
+
const { name, arguments: args } = request.params;
|
|
734
|
+
try {
|
|
735
|
+
const result = await callConvexTool(name, args || {});
|
|
736
|
+
return {
|
|
737
|
+
content: [
|
|
738
|
+
{
|
|
739
|
+
type: "text",
|
|
740
|
+
text: JSON.stringify(result, null, 2),
|
|
741
|
+
},
|
|
742
|
+
],
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
catch (error) {
|
|
746
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
747
|
+
return {
|
|
748
|
+
content: [
|
|
749
|
+
{
|
|
750
|
+
type: "text",
|
|
751
|
+
text: `Error: ${errorMessage}`,
|
|
752
|
+
},
|
|
753
|
+
],
|
|
754
|
+
isError: true,
|
|
755
|
+
};
|
|
756
|
+
}
|
|
757
|
+
});
|
|
758
|
+
// Start the server with stdio transport
|
|
759
|
+
async function main() {
|
|
760
|
+
const transport = new StdioServerTransport();
|
|
761
|
+
await server.connect(transport);
|
|
762
|
+
console.error("LifeOS MCP server running on stdio");
|
|
763
|
+
}
|
|
764
|
+
main().catch((error) => {
|
|
765
|
+
console.error("Fatal error:", error);
|
|
766
|
+
process.exit(1);
|
|
767
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@starascendin/lifeos-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for LifeOS Project Management - manage projects, tasks, notes, and contacts via AI assistants",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"lifeos-mcp": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"dev": "tsx src/index.ts",
|
|
17
|
+
"start": "node dist/index.js",
|
|
18
|
+
"prepublishOnly": "npm run build",
|
|
19
|
+
"version:patch": "npm version patch",
|
|
20
|
+
"version:minor": "npm version minor",
|
|
21
|
+
"version:major": "npm version major"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"mcp",
|
|
25
|
+
"model-context-protocol",
|
|
26
|
+
"lifeos",
|
|
27
|
+
"project-management",
|
|
28
|
+
"ai",
|
|
29
|
+
"claude",
|
|
30
|
+
"convex"
|
|
31
|
+
],
|
|
32
|
+
"author": "Bryan Liu",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/bryanliu/lifeos-mcp"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
46
|
+
"commander": "^14.0.2"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/node": "^20.0.0",
|
|
50
|
+
"tsx": "^4.0.0",
|
|
51
|
+
"typescript": "^5.0.0"
|
|
52
|
+
}
|
|
53
|
+
}
|