@loicngr/kobo 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.
Files changed (59) hide show
  1. package/AGENTS.md +227 -0
  2. package/LICENSE +674 -0
  3. package/README.md +199 -0
  4. package/dist/mcp-server/kobo-tasks-handlers.js +27 -0
  5. package/dist/mcp-server/kobo-tasks-server.js +116 -0
  6. package/dist/server/db/index.js +22 -0
  7. package/dist/server/db/migrations.js +20 -0
  8. package/dist/server/db/schema.js +49 -0
  9. package/dist/server/index.js +178 -0
  10. package/dist/server/routes/dev-server.js +74 -0
  11. package/dist/server/routes/git.js +20 -0
  12. package/dist/server/routes/notion.js +24 -0
  13. package/dist/server/routes/settings.js +92 -0
  14. package/dist/server/routes/workspaces.js +730 -0
  15. package/dist/server/services/agent-manager.js +435 -0
  16. package/dist/server/services/dev-server-service.js +298 -0
  17. package/dist/server/services/notion-service.js +369 -0
  18. package/dist/server/services/pr-template-service.js +38 -0
  19. package/dist/server/services/settings-service.js +205 -0
  20. package/dist/server/services/websocket-service.js +212 -0
  21. package/dist/server/services/workspace-service.js +208 -0
  22. package/dist/server/services/worktree-service.js +117 -0
  23. package/dist/server/utils/git-ops.js +117 -0
  24. package/dist/server/utils/paths.js +95 -0
  25. package/dist/server/utils/process-tracker.js +46 -0
  26. package/package.json +84 -0
  27. package/src/client/dist/spa/assets/ActivityFeed-BveJRagX.js +60 -0
  28. package/src/client/dist/spa/assets/ActivityFeed-DBNn62g_.css +1 -0
  29. package/src/client/dist/spa/assets/CreatePage-BlgXsrJO.css +1 -0
  30. package/src/client/dist/spa/assets/CreatePage-wbOkBwYU.js +2 -0
  31. package/src/client/dist/spa/assets/KFOMCnqEu92Fr1ME7kSn66aGLdTylUAMQXC89YmC2DPNWuYjalmUiAw-BepdiOnY.woff +0 -0
  32. package/src/client/dist/spa/assets/KFOMCnqEu92Fr1ME7kSn66aGLdTylUAMQXC89YmC2DPNWuZtalmUiAw-4ZhHFPot.woff +0 -0
  33. package/src/client/dist/spa/assets/KFOMCnqEu92Fr1ME7kSn66aGLdTylUAMQXC89YmC2DPNWuaabVmUiAw-CNa4tw4G.woff +0 -0
  34. package/src/client/dist/spa/assets/KFOMCnqEu92Fr1ME7kSn66aGLdTylUAMQXC89YmC2DPNWub2bVmUiAw-CHKg1YId.woff +0 -0
  35. package/src/client/dist/spa/assets/KFOMCnqEu92Fr1ME7kSn66aGLdTylUAMQXC89YmC2DPNWubEbFmUiAw-yBxCyPWP.woff +0 -0
  36. package/src/client/dist/spa/assets/KFOMCnqEu92Fr1ME7kSn66aGLdTylUAMQXC89YmC2DPNWubEbVmUiAw-3fZ6d7DD.woff +0 -0
  37. package/src/client/dist/spa/assets/MainLayout-6hzaLlYO.js +1 -0
  38. package/src/client/dist/spa/assets/MainLayout-D0OU6djX.css +1 -0
  39. package/src/client/dist/spa/assets/QBadge-Cb92Ia8-.js +1 -0
  40. package/src/client/dist/spa/assets/QDialog-B5H6ayTp.js +1 -0
  41. package/src/client/dist/spa/assets/QExpansionItem-DJgnAZg_.js +1 -0
  42. package/src/client/dist/spa/assets/QPage-CLk9i9z8.js +1 -0
  43. package/src/client/dist/spa/assets/QSpinnerDots-DcaNq8uL.js +1 -0
  44. package/src/client/dist/spa/assets/QTabPanels-DlG5TZhP.js +1 -0
  45. package/src/client/dist/spa/assets/QTooltip-637ruGFc.js +1 -0
  46. package/src/client/dist/spa/assets/SettingsPage-B9VYIQs-.css +1 -0
  47. package/src/client/dist/spa/assets/SettingsPage-KEqbLZUA.js +1 -0
  48. package/src/client/dist/spa/assets/WorkspacePage-BFuHLjou.css +1 -0
  49. package/src/client/dist/spa/assets/WorkspacePage-D0Hm21LY.js +2 -0
  50. package/src/client/dist/spa/assets/_plugin-vue_export-helper-CHpmshS7.js +1 -0
  51. package/src/client/dist/spa/assets/flUhRq6tzZclQEJ-Vdg-IuiaDsNa-Dr0goTwe.woff +0 -0
  52. package/src/client/dist/spa/assets/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ-D-x-0Q06.woff2 +0 -0
  53. package/src/client/dist/spa/assets/index-BThMCiY7.css +1 -0
  54. package/src/client/dist/spa/assets/index-CMvo3OTb.js +5 -0
  55. package/src/client/dist/spa/assets/nodes-DeIen-kp.js +1 -0
  56. package/src/client/dist/spa/assets/use-quasar-Dq-Vjx_2.js +1 -0
  57. package/src/client/dist/spa/index.html +4 -0
  58. package/src/mcp-server/kobo-tasks-handlers.ts +54 -0
  59. package/src/mcp-server/kobo-tasks-server.ts +128 -0
@@ -0,0 +1,128 @@
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 Database from 'better-sqlite3'
6
+ import { listTasksHandler, markTaskDoneHandler } from './kobo-tasks-handlers.js'
7
+
8
+ const workspaceId = process.env.KOBO_WORKSPACE_ID
9
+ const dbPath = process.env.KOBO_DB_PATH
10
+ const backendUrl = process.env.KOBO_BACKEND_URL ?? 'http://localhost:3000'
11
+
12
+ if (!workspaceId) {
13
+ console.error('[kobo-tasks-server] KOBO_WORKSPACE_ID env var is required')
14
+ process.exit(1)
15
+ }
16
+
17
+ if (!dbPath) {
18
+ console.error('[kobo-tasks-server] KOBO_DB_PATH env var is required')
19
+ process.exit(1)
20
+ }
21
+
22
+ let db: Database.Database
23
+ try {
24
+ db = new Database(dbPath, { readonly: false })
25
+ db.pragma('journal_mode = WAL')
26
+ db.pragma('foreign_keys = ON')
27
+ } catch (err) {
28
+ console.error('[kobo-tasks-server] Failed to open database:', err)
29
+ process.exit(1)
30
+ }
31
+
32
+ async function notifyBackend(taskId: string): Promise<void> {
33
+ try {
34
+ const url = `${backendUrl}/api/workspaces/${workspaceId}/tasks/${taskId}/notify-done`
35
+ const res = await fetch(url, { method: 'POST' })
36
+ if (!res.ok) {
37
+ console.error(`[kobo-tasks-server] notify-done HTTP ${res.status}`)
38
+ }
39
+ } catch (err) {
40
+ console.error('[kobo-tasks-server] notify-done failed:', err)
41
+ }
42
+ }
43
+
44
+ const server = new Server({ name: 'kobo-tasks', version: '1.0.0' }, { capabilities: { tools: {} } })
45
+
46
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
47
+ tools: [
48
+ {
49
+ name: 'list_tasks',
50
+ description:
51
+ 'List all tasks and acceptance criteria for the current workspace with their IDs and current status. Call this first to discover task IDs before calling mark_task_done.',
52
+ inputSchema: {
53
+ type: 'object',
54
+ properties: {},
55
+ required: [],
56
+ },
57
+ },
58
+ {
59
+ name: 'mark_task_done',
60
+ description:
61
+ 'Mark a task or acceptance criterion as done. Use this when you have completed the work for a criterion and validated it.',
62
+ inputSchema: {
63
+ type: 'object',
64
+ properties: {
65
+ task_id: {
66
+ type: 'string',
67
+ description: 'The ID of the task to mark as done (obtained from list_tasks)',
68
+ },
69
+ },
70
+ required: ['task_id'],
71
+ },
72
+ },
73
+ ],
74
+ }))
75
+
76
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
77
+ const { name, arguments: args } = request.params
78
+
79
+ if (name === 'list_tasks') {
80
+ const tasks = listTasksHandler(db, workspaceId!)
81
+ return {
82
+ content: [{ type: 'text', text: JSON.stringify(tasks, null, 2) }],
83
+ }
84
+ }
85
+
86
+ if (name === 'mark_task_done') {
87
+ const taskId = (args as { task_id?: string })?.task_id
88
+ if (!taskId) {
89
+ return {
90
+ content: [{ type: 'text', text: 'Error: task_id parameter is required' }],
91
+ isError: true,
92
+ }
93
+ }
94
+ try {
95
+ const result = markTaskDoneHandler(db, workspaceId!, taskId)
96
+ void notifyBackend(taskId)
97
+ return {
98
+ content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
99
+ }
100
+ } catch (err) {
101
+ const message = err instanceof Error ? err.message : String(err)
102
+ return {
103
+ content: [{ type: 'text', text: `Error: ${message}` }],
104
+ isError: true,
105
+ }
106
+ }
107
+ }
108
+
109
+ return {
110
+ content: [{ type: 'text', text: `Unknown tool: ${name}` }],
111
+ isError: true,
112
+ }
113
+ })
114
+
115
+ const transport = new StdioServerTransport()
116
+ server.connect(transport).catch((err) => {
117
+ console.error('[kobo-tasks-server] Fatal:', err)
118
+ process.exit(1)
119
+ })
120
+
121
+ process.on('SIGTERM', () => {
122
+ db.close()
123
+ process.exit(0)
124
+ })
125
+ process.on('SIGINT', () => {
126
+ db.close()
127
+ process.exit(0)
128
+ })