obsidian-accomplishments-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.
Files changed (119) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +349 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +120 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/models/types.d.ts +136 -0
  8. package/dist/models/types.d.ts.map +1 -0
  9. package/dist/models/types.js +27 -0
  10. package/dist/models/types.js.map +1 -0
  11. package/dist/parsers/canvas-parser.d.ts +58 -0
  12. package/dist/parsers/canvas-parser.d.ts.map +1 -0
  13. package/dist/parsers/canvas-parser.js +136 -0
  14. package/dist/parsers/canvas-parser.js.map +1 -0
  15. package/dist/parsers/markdown-parser.d.ts +22 -0
  16. package/dist/parsers/markdown-parser.d.ts.map +1 -0
  17. package/dist/parsers/markdown-parser.js +254 -0
  18. package/dist/parsers/markdown-parser.js.map +1 -0
  19. package/dist/services/accomplishment-service.d.ts +33 -0
  20. package/dist/services/accomplishment-service.d.ts.map +1 -0
  21. package/dist/services/accomplishment-service.js +284 -0
  22. package/dist/services/accomplishment-service.js.map +1 -0
  23. package/dist/services/canvas-service.d.ts +52 -0
  24. package/dist/services/canvas-service.d.ts.map +1 -0
  25. package/dist/services/canvas-service.js +166 -0
  26. package/dist/services/canvas-service.js.map +1 -0
  27. package/dist/services/context-doc-service.d.ts +70 -0
  28. package/dist/services/context-doc-service.d.ts.map +1 -0
  29. package/dist/services/context-doc-service.js +229 -0
  30. package/dist/services/context-doc-service.js.map +1 -0
  31. package/dist/services/dependency-service.d.ts +22 -0
  32. package/dist/services/dependency-service.d.ts.map +1 -0
  33. package/dist/services/dependency-service.js +99 -0
  34. package/dist/services/dependency-service.js.map +1 -0
  35. package/dist/services/task-service.d.ts +32 -0
  36. package/dist/services/task-service.d.ts.map +1 -0
  37. package/dist/services/task-service.js +152 -0
  38. package/dist/services/task-service.js.map +1 -0
  39. package/dist/test-runner.d.ts +6 -0
  40. package/dist/test-runner.d.ts.map +1 -0
  41. package/dist/test-runner.js +130 -0
  42. package/dist/test-runner.js.map +1 -0
  43. package/dist/tools/get-accomplishment.d.ts +26 -0
  44. package/dist/tools/get-accomplishment.d.ts.map +1 -0
  45. package/dist/tools/get-accomplishment.js +53 -0
  46. package/dist/tools/get-accomplishment.js.map +1 -0
  47. package/dist/tools/get-blocked-items.d.ts +15 -0
  48. package/dist/tools/get-blocked-items.d.ts.map +1 -0
  49. package/dist/tools/get-blocked-items.js +72 -0
  50. package/dist/tools/get-blocked-items.js.map +1 -0
  51. package/dist/tools/get-current-work.d.ts +15 -0
  52. package/dist/tools/get-current-work.d.ts.map +1 -0
  53. package/dist/tools/get-current-work.js +67 -0
  54. package/dist/tools/get-current-work.js.map +1 -0
  55. package/dist/tools/get-project-status.d.ts +26 -0
  56. package/dist/tools/get-project-status.d.ts.map +1 -0
  57. package/dist/tools/get-project-status.js +92 -0
  58. package/dist/tools/get-project-status.js.map +1 -0
  59. package/dist/tools/get-ready-to-start.d.ts +15 -0
  60. package/dist/tools/get-ready-to-start.d.ts.map +1 -0
  61. package/dist/tools/get-ready-to-start.js +46 -0
  62. package/dist/tools/get-ready-to-start.js.map +1 -0
  63. package/dist/tools/index.d.ts +155 -0
  64. package/dist/tools/index.d.ts.map +1 -0
  65. package/dist/tools/index.js +48 -0
  66. package/dist/tools/index.js.map +1 -0
  67. package/dist/tools/list-accomplishments.d.ts +34 -0
  68. package/dist/tools/list-accomplishments.d.ts.map +1 -0
  69. package/dist/tools/list-accomplishments.js +34 -0
  70. package/dist/tools/list-accomplishments.js.map +1 -0
  71. package/dist/tools/list-files.d.ts +26 -0
  72. package/dist/tools/list-files.d.ts.map +1 -0
  73. package/dist/tools/list-files.js +46 -0
  74. package/dist/tools/list-files.js.map +1 -0
  75. package/dist/tools/list-workspaces.d.ts +22 -0
  76. package/dist/tools/list-workspaces.d.ts.map +1 -0
  77. package/dist/tools/list-workspaces.js +22 -0
  78. package/dist/tools/list-workspaces.js.map +1 -0
  79. package/dist/tools/manage-accomplishment.d.ts +147 -0
  80. package/dist/tools/manage-accomplishment.d.ts.map +1 -0
  81. package/dist/tools/manage-accomplishment.js +138 -0
  82. package/dist/tools/manage-accomplishment.js.map +1 -0
  83. package/dist/tools/manage-dependency.d.ts +41 -0
  84. package/dist/tools/manage-dependency.d.ts.map +1 -0
  85. package/dist/tools/manage-dependency.js +61 -0
  86. package/dist/tools/manage-dependency.js.map +1 -0
  87. package/dist/tools/manage-task.d.ts +119 -0
  88. package/dist/tools/manage-task.d.ts.map +1 -0
  89. package/dist/tools/manage-task.js +121 -0
  90. package/dist/tools/manage-task.js.map +1 -0
  91. package/dist/tools/read-docs.d.ts +48 -0
  92. package/dist/tools/read-docs.d.ts.map +1 -0
  93. package/dist/tools/read-docs.js +90 -0
  94. package/dist/tools/read-docs.js.map +1 -0
  95. package/dist/tools/set-work-focus.d.ts +48 -0
  96. package/dist/tools/set-work-focus.d.ts.map +1 -0
  97. package/dist/tools/set-work-focus.js +75 -0
  98. package/dist/tools/set-work-focus.js.map +1 -0
  99. package/dist/tools/sync-dependencies.d.ts +33 -0
  100. package/dist/tools/sync-dependencies.d.ts.map +1 -0
  101. package/dist/tools/sync-dependencies.js +144 -0
  102. package/dist/tools/sync-dependencies.js.map +1 -0
  103. package/dist/tools/update-doc.d.ts +62 -0
  104. package/dist/tools/update-doc.d.ts.map +1 -0
  105. package/dist/tools/update-doc.js +196 -0
  106. package/dist/tools/update-doc.js.map +1 -0
  107. package/dist/utils/config.d.ts +27 -0
  108. package/dist/utils/config.d.ts.map +1 -0
  109. package/dist/utils/config.js +106 -0
  110. package/dist/utils/config.js.map +1 -0
  111. package/dist/utils/file-utils.d.ts +29 -0
  112. package/dist/utils/file-utils.d.ts.map +1 -0
  113. package/dist/utils/file-utils.js +83 -0
  114. package/dist/utils/file-utils.js.map +1 -0
  115. package/dist/utils/positioning.d.ts +16 -0
  116. package/dist/utils/positioning.d.ts.map +1 -0
  117. package/dist/utils/positioning.js +126 -0
  118. package/dist/utils/positioning.js.map +1 -0
  119. package/package.json +56 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Ostan Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,349 @@
1
+ # Obsidian MCP Server
2
+
3
+ An MCP (Model Context Protocol) server that enables AI assistants to manage structured project accomplishments in Obsidian. Works alongside the [Canvas Structured Items Plugin](https://bitbucket.org/ostanmarc/obsidian-canvas-structured-items/src/master/) for visual project management.
4
+
5
+ ## What This Does
6
+
7
+ This MCP server lets AI assistants:
8
+ - **Manage accomplishments** — create, update, and track work items with outcomes, acceptance criteria, and tasks
9
+ - **Handle dependencies** — define what blocks what, find blocked items, and identify what's ready to start
10
+ - **Track progress** — see project status, current work, and completion statistics
11
+ - **Read and write documents** — access reference materials organized in workspaces
12
+
13
+ ```
14
+ ┌─────────────────────────────────────────────────────────────────────┐
15
+ │ Your Workflow │
16
+ ├─────────────────────────────────────────────────────────────────────┤
17
+ │ │
18
+ │ ┌──────────┐ ┌──────────────┐ ┌──────────┐ │
19
+ │ │ Obsidian │◄────►│ MCP Server │◄────►│ AI │ │
20
+ │ │ Canvas │ │ (this repo) │ │ Assistant│ │
21
+ │ └────┬─────┘ └──────────────┘ └──────────┘ │
22
+ │ │ │
23
+ │ ▼ │
24
+ │ ┌──────────┐ ┌──────────────┐ │
25
+ │ │ Plugin │─────►│ Notion │ (optional sync) │
26
+ │ └──────────┘ └──────────────┘ │
27
+ │ │
28
+ └─────────────────────────────────────────────────────────────────────┘
29
+ ```
30
+
31
+ ---
32
+
33
+ ## Installation
34
+
35
+ ### Prerequisites
36
+
37
+ - Node.js 18 or later
38
+ - An Obsidian vault
39
+ - The [Canvas Structured Items Plugin](https://bitbucket.org/ostanmarc/obsidian-canvas-structured-items/src/master/) installed in your vault
40
+
41
+ ### Option 1: Install from npm (Recommended)
42
+
43
+ ```bash
44
+ npm install -g obsidian-accomplishments-mcp
45
+ ```
46
+
47
+ Or run directly with npx:
48
+
49
+ ```bash
50
+ npx obsidian-accomplishments-mcp
51
+ ```
52
+
53
+ ### Option 2: Install from Source
54
+
55
+ ```bash
56
+ git clone https://github.com/ostanlabs/obsidian_mcp.git
57
+ cd obsidian_mcp
58
+ npm install
59
+ npm run build
60
+ ```
61
+
62
+ ### Set Up Your Vault
63
+
64
+ Create the required folder structure in your Obsidian vault:
65
+
66
+ ```
67
+ your-vault/
68
+ ├── accomplishments/ # Accomplishment markdown files
69
+ ├── projects/
70
+ │ └── main.canvas # Your project canvas
71
+ └── workspaces.json # Workspace configuration (auto-created on first run)
72
+ ```
73
+
74
+ ### Configure Your AI Assistant
75
+
76
+ Add the MCP server to your AI client's configuration.
77
+
78
+ **For Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
79
+
80
+ Using npx (recommended):
81
+ ```json
82
+ {
83
+ "mcpServers": {
84
+ "obsidian": {
85
+ "command": "npx",
86
+ "args": ["-y", "obsidian-accomplishments-mcp@latest"],
87
+ "env": {
88
+ "VAULT_PATH": "/absolute/path/to/your/obsidian/vault",
89
+ "ACCOMPLISHMENTS_FOLDER": "accomplishments",
90
+ "DEFAULT_CANVAS": "projects/main.canvas"
91
+ }
92
+ }
93
+ }
94
+ }
95
+ ```
96
+
97
+ Using global install:
98
+ ```json
99
+ {
100
+ "mcpServers": {
101
+ "obsidian": {
102
+ "command": "obsidian-accomplishments-mcp",
103
+ "env": {
104
+ "VAULT_PATH": "/absolute/path/to/your/obsidian/vault",
105
+ "ACCOMPLISHMENTS_FOLDER": "accomplishments",
106
+ "DEFAULT_CANVAS": "projects/main.canvas"
107
+ }
108
+ }
109
+ }
110
+ }
111
+ ```
112
+
113
+ Using local install:
114
+ ```json
115
+ {
116
+ "mcpServers": {
117
+ "obsidian": {
118
+ "command": "node",
119
+ "args": ["/path/to/obsidian_mcp/dist/index.js"],
120
+ "env": {
121
+ "VAULT_PATH": "/absolute/path/to/your/obsidian/vault",
122
+ "ACCOMPLISHMENTS_FOLDER": "accomplishments",
123
+ "DEFAULT_CANVAS": "projects/main.canvas"
124
+ }
125
+ }
126
+ }
127
+ }
128
+ ```
129
+
130
+ #### Environment Variables
131
+
132
+ | Variable | Required | Description |
133
+ |----------|----------|-------------|
134
+ | `VAULT_PATH` | Yes | Absolute path to your Obsidian vault |
135
+ | `ACCOMPLISHMENTS_FOLDER` | Yes | Folder for accomplishment files (relative to vault) |
136
+ | `DEFAULT_CANVAS` | Yes | Path to your main project canvas file (relative to vault) |
137
+
138
+ ### Configure Workspaces
139
+
140
+ On first run, the server creates a `workspaces.json` file in your vault. Edit this file to define document workspaces that the AI can access:
141
+
142
+ ```json
143
+ {
144
+ "docs": {
145
+ "path": "/absolute/path/to/your/vault/docs",
146
+ "description": "Project documentation and reference materials"
147
+ },
148
+ "notes": {
149
+ "path": "/absolute/path/to/your/vault/notes",
150
+ "description": "Meeting notes and daily logs"
151
+ }
152
+ }
153
+ ```
154
+
155
+ Each workspace is a named folder containing markdown files that the AI can read and write.
156
+
157
+ ---
158
+
159
+ ## Core Concepts
160
+
161
+ ### Accomplishments
162
+
163
+ An **accomplishment** is the atomic unit of work. Each accomplishment has:
164
+
165
+ - **Title** — A clear name for the work item
166
+ - **Outcome** — What will be true when this is done
167
+ - **Acceptance Criteria** — Checkboxes defining completion
168
+ - **Tasks** — Specific steps to achieve the outcome
169
+ - **Dependencies** — Other accomplishments that must finish first
170
+ - **Status** — Not Started, In Progress, Completed, or Blocked
171
+ - **Effort Type** — Business, Engineering, Infra, or Research
172
+ - **Priority** — Low, Medium, High, or Critical
173
+
174
+ Example accomplishment file:
175
+
176
+ ```markdown
177
+ ---
178
+ type: accomplishment
179
+ title: User Authentication
180
+ id: ACC-001
181
+ effort: Engineering
182
+ status: In Progress
183
+ priority: High
184
+ inProgress: true
185
+ depends_on: ["ACC-000"]
186
+ ---
187
+
188
+ # User Authentication (Accomplishment)
189
+
190
+ ## Outcome
191
+ Users can securely log in and maintain sessions.
192
+
193
+ ## Acceptance Criteria
194
+ - [ ] Login form validates credentials
195
+ - [ ] Sessions persist across browser refreshes
196
+ - [ ] Logout clears session completely
197
+
198
+ ## Tasks
199
+
200
+ ### Task 1: Design Auth Flow
201
+ - **Goal:** Document the authentication sequence
202
+ - **Estimate:** 2h
203
+ - **Status:** Complete
204
+
205
+ ### Task 2: Implement Login API
206
+ - **Goal:** Create backend authentication endpoint
207
+ - **Estimate:** 4h
208
+ - **Status:** InProgress
209
+ ```
210
+
211
+ ### Canvas as Project Board
212
+
213
+ The `.canvas` file provides a visual project view:
214
+
215
+ - **Nodes** = Accomplishments (colored by effort type)
216
+ - **Arrows** = Dependencies (A → B means "B depends on A")
217
+ - **Position** = Workflow stage (left-to-right progression)
218
+ - **Red border** = Currently being worked on (`inProgress: true`)
219
+
220
+ ### Workspaces
221
+
222
+ Workspaces are named document collections that the AI can access. Configure them in `workspaces.json` to give the AI access to:
223
+ - Project documentation
224
+ - Meeting notes
225
+ - Reference materials
226
+ - Any other markdown files
227
+
228
+ ---
229
+
230
+ ## Available Tools
231
+
232
+ The MCP server provides 14 tools organized by function:
233
+
234
+ ### Accomplishment Management
235
+
236
+ | Tool | Description |
237
+ |------|-------------|
238
+ | `manage_accomplishment` | Create, update, or delete accomplishments |
239
+ | `get_accomplishment` | Get full details of a specific accomplishment |
240
+ | `list_accomplishments` | List all accomplishments with optional status filter |
241
+
242
+ ### Task Management
243
+
244
+ | Tool | Description |
245
+ |------|-------------|
246
+ | `manage_task` | Add, update, or remove tasks within an accomplishment |
247
+ | `set_work_focus` | Set which accomplishment/task is currently being worked on |
248
+
249
+ ### Dependency Management
250
+
251
+ | Tool | Description |
252
+ |------|-------------|
253
+ | `manage_dependency` | Add or remove dependencies between accomplishments |
254
+
255
+ ### Project Status
256
+
257
+ | Tool | Description |
258
+ |------|-------------|
259
+ | `get_project_status` | Get project statistics and overview |
260
+ | `get_current_work` | Get items marked as in-progress |
261
+ | `get_blocked_items` | Get items waiting on incomplete dependencies |
262
+ | `get_ready_to_start` | Get items with all dependencies complete |
263
+
264
+ ### Document Management
265
+
266
+ | Tool | Description |
267
+ |------|-------------|
268
+ | `list_workspaces` | List all configured workspaces |
269
+ | `list_files` | List all markdown files in a workspace |
270
+ | `read_docs` | Read a document from a workspace |
271
+ | `update_doc` | Create, update, or delete documents in a workspace |
272
+
273
+ ---
274
+
275
+ ## Usage Examples
276
+
277
+ Once configured, ask your AI assistant things like:
278
+
279
+ ### Project Overview
280
+ > "What's the status of my project?"
281
+ > "Show me what's currently in progress"
282
+ > "What items are blocked?"
283
+ > "What can I start working on?"
284
+
285
+ ### Managing Accomplishments
286
+ > "Create an accomplishment for building the payment system"
287
+ > "Mark ACC-001 as complete"
288
+ > "Set ACC-005 as my current focus"
289
+ > "What are the details of ACC-003?"
290
+
291
+ ### Managing Tasks
292
+ > "Add a task to ACC-003 for writing unit tests"
293
+ > "Mark task 2 of ACC-001 as complete"
294
+ > "What tasks are left on ACC-002?"
295
+
296
+ ### Dependencies
297
+ > "ACC-004 depends on ACC-002 and ACC-003"
298
+ > "Remove the dependency from ACC-005 to ACC-001"
299
+ > "What's blocking ACC-006?"
300
+
301
+ ### Documents
302
+ > "What workspaces are available?"
303
+ > "List files in the docs workspace"
304
+ > "Read the architecture document"
305
+ > "Add a section about API design to the architecture doc"
306
+ > "Create a new meeting notes document"
307
+
308
+ ---
309
+
310
+ ## Notion Sync (Optional)
311
+
312
+ The [Canvas Structured Items Plugin](https://bitbucket.org/ostanmarc/obsidian-canvas-structured-items/src/master/) can sync accomplishments to Notion:
313
+
314
+ 1. Configure Notion API key and database ID in the plugin settings
315
+ 2. Accomplishments sync automatically when saved
316
+ 3. Dependencies become Notion relations
317
+ 4. Two-way sync keeps both systems updated
318
+
319
+ This lets your team see project status in Notion while you manage everything from Obsidian.
320
+
321
+ ---
322
+
323
+ ## Development
324
+
325
+ ```bash
326
+ # Build the project
327
+ npm run build
328
+
329
+ # Watch mode for development
330
+ npm run dev
331
+
332
+ # Run tests
333
+ npm test
334
+ ```
335
+
336
+ The server communicates via MCP protocol over stdio. Test by configuring it in an MCP-compatible client.
337
+
338
+ ---
339
+
340
+ ## Technical Reference
341
+
342
+ For detailed API specifications, data models, and implementation details, see [Technical Specification](docs/MCP_TECHNICAL_SPEC.md).
343
+
344
+ ---
345
+
346
+ ## License
347
+
348
+ MIT
349
+
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
5
+ import { getConfig } from './utils/config.js';
6
+ import { MCPError } from './models/types.js';
7
+ import { allToolDefinitions, handleManageAccomplishment, handleManageDependency, handleManageTask, handleSetWorkFocus, handleGetAccomplishment, handleListAccomplishments, handleGetCurrentWork, handleGetBlockedItems, handleGetReadyToStart, handleGetProjectStatus, handleReadDocs, handleUpdateDoc, handleListWorkspaces, handleListFiles, } from './tools/index.js';
8
+ // Create server instance
9
+ const server = new Server({
10
+ name: 'obsidian-accomplishments',
11
+ version: '1.0.0',
12
+ }, {
13
+ capabilities: {
14
+ tools: {},
15
+ },
16
+ });
17
+ // Get configuration
18
+ let config;
19
+ try {
20
+ config = getConfig();
21
+ }
22
+ catch (error) {
23
+ console.error('Configuration error:', error);
24
+ process.exit(1);
25
+ }
26
+ // Register tool list handler
27
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
28
+ return {
29
+ tools: allToolDefinitions,
30
+ };
31
+ });
32
+ // Register tool call handler
33
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
34
+ const { name, arguments: args } = request.params;
35
+ try {
36
+ let result;
37
+ switch (name) {
38
+ case 'manage_accomplishment':
39
+ result = await handleManageAccomplishment(config, args);
40
+ break;
41
+ case 'manage_dependency':
42
+ result = await handleManageDependency(config, args);
43
+ break;
44
+ case 'manage_task':
45
+ result = await handleManageTask(config, args);
46
+ break;
47
+ case 'set_work_focus':
48
+ result = await handleSetWorkFocus(config, args);
49
+ break;
50
+ case 'get_accomplishment':
51
+ result = await handleGetAccomplishment(config, args);
52
+ break;
53
+ case 'list_accomplishments':
54
+ result = await handleListAccomplishments(config, args);
55
+ break;
56
+ case 'get_current_work':
57
+ result = await handleGetCurrentWork(config, args);
58
+ break;
59
+ case 'get_blocked_items':
60
+ result = await handleGetBlockedItems(config, args);
61
+ break;
62
+ case 'get_ready_to_start':
63
+ result = await handleGetReadyToStart(config, args);
64
+ break;
65
+ case 'get_project_status':
66
+ result = await handleGetProjectStatus(config, args);
67
+ break;
68
+ case 'read_docs':
69
+ result = await handleReadDocs(config, args);
70
+ break;
71
+ case 'update_doc':
72
+ result = await handleUpdateDoc(config, args);
73
+ break;
74
+ case 'list_workspaces':
75
+ result = await handleListWorkspaces(config, args);
76
+ break;
77
+ case 'list_files':
78
+ result = await handleListFiles(config, args);
79
+ break;
80
+ default:
81
+ throw new MCPError(`Unknown tool: ${name}`, 'UNKNOWN_TOOL', 400);
82
+ }
83
+ return {
84
+ content: [
85
+ {
86
+ type: 'text',
87
+ text: JSON.stringify(result, null, 2),
88
+ },
89
+ ],
90
+ };
91
+ }
92
+ catch (error) {
93
+ const errorMessage = error instanceof Error ? error.message : String(error);
94
+ const errorCode = error instanceof MCPError ? error.code : 'INTERNAL_ERROR';
95
+ return {
96
+ content: [
97
+ {
98
+ type: 'text',
99
+ text: JSON.stringify({
100
+ error: true,
101
+ code: errorCode,
102
+ message: errorMessage,
103
+ }, null, 2),
104
+ },
105
+ ],
106
+ isError: true,
107
+ };
108
+ }
109
+ });
110
+ // Start the server
111
+ async function main() {
112
+ const transport = new StdioServerTransport();
113
+ await server.connect(transport);
114
+ console.error('Obsidian Accomplishments MCP Server running on stdio');
115
+ }
116
+ main().catch((error) => {
117
+ console.error('Fatal error:', error);
118
+ process.exit(1);
119
+ });
120
+ //# 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,136 @@
1
+ export type AccomplishmentStatus = 'Not Started' | 'In Progress' | 'Completed' | 'Blocked';
2
+ export type TaskStatus = 'Open' | 'InProgress' | 'Complete' | 'OnHold';
3
+ export type Effort = 'Business' | 'Infra' | 'Engineering' | 'Research';
4
+ export type Priority = 'Low' | 'Medium' | 'High' | 'Critical';
5
+ export interface AccomplishmentFrontmatter {
6
+ type: 'accomplishment';
7
+ title: string;
8
+ id: string;
9
+ effort: Effort;
10
+ status: AccomplishmentStatus;
11
+ priority: Priority;
12
+ inProgress: boolean;
13
+ depends_on: string[];
14
+ created_by_plugin: boolean;
15
+ collapsed_height: number;
16
+ expanded_height: number;
17
+ expanded_width: number;
18
+ created: string;
19
+ updated: string;
20
+ canvas_source: string;
21
+ vault_path: string;
22
+ notion_page_id?: string;
23
+ }
24
+ export interface Task {
25
+ number: number;
26
+ name: string;
27
+ goal: string;
28
+ description: string;
29
+ technical_notes?: string;
30
+ estimate?: number;
31
+ status: TaskStatus;
32
+ notes?: string;
33
+ }
34
+ export interface Accomplishment {
35
+ frontmatter: AccomplishmentFrontmatter;
36
+ outcome: string;
37
+ acceptance_criteria: string[];
38
+ tasks: Task[];
39
+ notes: string;
40
+ is_blocked?: boolean;
41
+ }
42
+ export interface AccomplishmentSummary {
43
+ id: string;
44
+ title: string;
45
+ status: AccomplishmentStatus;
46
+ priority: Priority;
47
+ effort: Effort;
48
+ inProgress: boolean;
49
+ is_blocked: boolean;
50
+ depends_on: string[];
51
+ task_count: number;
52
+ completed_task_count: number;
53
+ }
54
+ export interface CanvasNode {
55
+ id: string;
56
+ type: 'file' | 'text' | 'link' | 'group';
57
+ file?: string;
58
+ text?: string;
59
+ url?: string;
60
+ x: number;
61
+ y: number;
62
+ width: number;
63
+ height: number;
64
+ color?: string;
65
+ }
66
+ export interface CanvasEdge {
67
+ id: string;
68
+ fromNode: string;
69
+ toNode: string;
70
+ fromSide: 'top' | 'right' | 'bottom' | 'left';
71
+ toSide: 'top' | 'right' | 'bottom' | 'left';
72
+ color?: string;
73
+ label?: string;
74
+ }
75
+ export interface CanvasFile {
76
+ nodes: CanvasNode[];
77
+ edges: CanvasEdge[];
78
+ }
79
+ export interface CreateAccomplishmentData {
80
+ title: string;
81
+ effort: Effort;
82
+ priority?: Priority;
83
+ status?: AccomplishmentStatus;
84
+ outcome?: string;
85
+ acceptance_criteria?: string[];
86
+ depends_on?: string[];
87
+ canvas_source?: string;
88
+ }
89
+ export interface UpdateAccomplishmentData {
90
+ title?: string;
91
+ effort?: Effort;
92
+ priority?: Priority;
93
+ status?: AccomplishmentStatus;
94
+ inProgress?: boolean;
95
+ outcome?: string;
96
+ acceptance_criteria?: string[];
97
+ notes?: string;
98
+ }
99
+ export interface TaskData {
100
+ name: string;
101
+ goal: string;
102
+ description?: string;
103
+ technical_notes?: string;
104
+ estimate?: number;
105
+ status?: TaskStatus;
106
+ notes?: string;
107
+ }
108
+ export interface WorkspaceConfig {
109
+ path: string;
110
+ description: string;
111
+ }
112
+ export interface Config {
113
+ vaultPath: string;
114
+ accomplishmentsFolder: string;
115
+ defaultCanvas: string;
116
+ workspaces: Record<string, WorkspaceConfig>;
117
+ }
118
+ export interface Position {
119
+ x: number;
120
+ y: number;
121
+ }
122
+ export declare class MCPError extends Error {
123
+ code: string;
124
+ statusCode: number;
125
+ constructor(message: string, code: string, statusCode?: number);
126
+ }
127
+ export declare class NotFoundError extends MCPError {
128
+ constructor(message: string);
129
+ }
130
+ export declare class ValidationError extends MCPError {
131
+ constructor(message: string);
132
+ }
133
+ export declare class ConflictError extends MCPError {
134
+ constructor(message: string);
135
+ }
136
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/models/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ // Error types
2
+ export class MCPError extends Error {
3
+ code;
4
+ statusCode;
5
+ constructor(message, code, statusCode = 500) {
6
+ super(message);
7
+ this.code = code;
8
+ this.statusCode = statusCode;
9
+ this.name = 'MCPError';
10
+ }
11
+ }
12
+ export class NotFoundError extends MCPError {
13
+ constructor(message) {
14
+ super(message, 'NOT_FOUND', 404);
15
+ }
16
+ }
17
+ export class ValidationError extends MCPError {
18
+ constructor(message) {
19
+ super(message, 'VALIDATION_ERROR', 400);
20
+ }
21
+ }
22
+ export class ConflictError extends MCPError {
23
+ constructor(message) {
24
+ super(message, 'CONFLICT', 409);
25
+ }
26
+ }
27
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/models/types.ts"],"names":[],"mappings":"AAoJA,cAAc;AACd,MAAM,OAAO,QAAS,SAAQ,KAAK;IAGxB;IACA;IAHT,YACE,OAAe,EACR,IAAY,EACZ,aAAqB,GAAG;QAE/B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,SAAI,GAAJ,IAAI,CAAQ;QACZ,eAAU,GAAV,UAAU,CAAc;QAG/B,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,QAAQ;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,QAAQ;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,CAAC,CAAC;IAC1C,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,QAAQ;IACzC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;IAClC,CAAC;CACF"}