sprint-artifact 0.2.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/LICENSE +1 -0
- package/README.md +161 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +157 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +180 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/sdk/google-drive.d.ts +15 -0
- package/dist/sdk/google-drive.d.ts.map +1 -0
- package/dist/sdk/google-drive.js +114 -0
- package/dist/sdk/google-drive.js.map +1 -0
- package/dist/sdk/index.d.ts +4 -0
- package/dist/sdk/index.d.ts.map +1 -0
- package/dist/sdk/index.js +3 -0
- package/dist/sdk/index.js.map +1 -0
- package/dist/sdk/sprint-artifact.d.ts +29 -0
- package/dist/sdk/sprint-artifact.d.ts.map +1 -0
- package/dist/sdk/sprint-artifact.js +142 -0
- package/dist/sdk/sprint-artifact.js.map +1 -0
- package/dist/types/index.d.ts +77 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/config.d.ts +9 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +50 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/oauth2.d.ts +12 -0
- package/dist/utils/oauth2.d.ts.map +1 -0
- package/dist/utils/oauth2.js +148 -0
- package/dist/utils/oauth2.js.map +1 -0
- package/package.json +72 -0
package/LICENSE
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
MIT License
|
package/README.md
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Sprint Artifact
|
|
2
|
+
|
|
3
|
+
Sprint Artifact management tool with Google Drive integration.
|
|
4
|
+
|
|
5
|
+
Manage your sprint artifacts (BRD, PRD, tasks, backlogs) directly from CLI or AI assistants (Cursor, Claude, Codex, OpenCode).
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **CLI** - Full command-line interface for sprint management
|
|
10
|
+
- **MCP Server** - Integration with AI coding assistants
|
|
11
|
+
- **SDK** - Programmatic access for custom workflows
|
|
12
|
+
- **Google Drive Sync** - Bi-directional sync with Google Drive
|
|
13
|
+
- **OAuth2 Login** - Simple Google account login for team members
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
### Install
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install -g sprint-artifact
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Setup Google Cloud
|
|
24
|
+
|
|
25
|
+
1. Buka [Google Cloud Console](https://console.cloud.google.com)
|
|
26
|
+
2. Buat/select project
|
|
27
|
+
3. Enable **Google Drive API** (APIs & Services > Library)
|
|
28
|
+
4. Buat **OAuth consent screen** (APIs & Services > OAuth consent screen)
|
|
29
|
+
- User Type: **Internal** (Workspace) atau **External**
|
|
30
|
+
- App name: `sprint-artifact`
|
|
31
|
+
5. Buat **OAuth 2.0 Client ID** (APIs & Services > Credentials)
|
|
32
|
+
- Application type: **Desktop app**
|
|
33
|
+
- Download JSON
|
|
34
|
+
|
|
35
|
+
### Login
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Taruh credentials.json di folder project atau ~/.sprint-artifact/
|
|
39
|
+
cp ~/Downloads/credentials.json ./credentials.json
|
|
40
|
+
|
|
41
|
+
# Login dengan Google account
|
|
42
|
+
sprint-artifact login
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Browser terbuka > pilih akun Google > selesai.
|
|
46
|
+
|
|
47
|
+
### Initialize Project
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Buat folder di Google Drive, copy folder ID dari URL
|
|
51
|
+
sprint-artifact init --folder-id <GOOGLE_DRIVE_FOLDER_ID>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## CLI Commands
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Login dengan Google account
|
|
58
|
+
sprint-artifact login [--credentials <path>]
|
|
59
|
+
|
|
60
|
+
# Initialize project
|
|
61
|
+
sprint-artifact init --folder-id <FOLDER_ID>
|
|
62
|
+
|
|
63
|
+
# Buat backlog item
|
|
64
|
+
sprint-artifact backlog create --title "Feature" --desc "Description" --priority high
|
|
65
|
+
|
|
66
|
+
# Sync dengan Google Drive
|
|
67
|
+
sprint-artifact sync
|
|
68
|
+
|
|
69
|
+
# Lihat status
|
|
70
|
+
sprint-artifact status
|
|
71
|
+
|
|
72
|
+
# Pilih task yang sedang dikerjakan
|
|
73
|
+
sprint-artifact select <TASK_ID>
|
|
74
|
+
|
|
75
|
+
# Pindahkan backlog ke sprint
|
|
76
|
+
sprint-artifact sprint move --backlog-id <ID> --sprint-id <ID>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## MCP Server
|
|
80
|
+
|
|
81
|
+
Tambahkan ke konfigurasi MCP (Cursor, Claude, dll):
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"mcpServers": {
|
|
86
|
+
"sprint-artifact": {
|
|
87
|
+
"command": "sprint-artifact",
|
|
88
|
+
"args": ["mcp"]
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Available Tools
|
|
95
|
+
|
|
96
|
+
| Tool | Description |
|
|
97
|
+
|------|-------------|
|
|
98
|
+
| `backlog_create` | Buat backlog item baru |
|
|
99
|
+
| `sync_documents` | Sync dokumen dengan Google Drive |
|
|
100
|
+
| `move_to_sprint` | Pindahkan backlog ke sprint |
|
|
101
|
+
| `status` | Lihat status project |
|
|
102
|
+
| `select_task` | Pilih task yang sedang dikerjakan |
|
|
103
|
+
|
|
104
|
+
## SDK Usage
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
import { SprintArtifact } from 'sprint-artifact';
|
|
108
|
+
|
|
109
|
+
const artifact = new SprintArtifact(process.cwd());
|
|
110
|
+
|
|
111
|
+
// Login (hanya perlu sekali)
|
|
112
|
+
await artifact.init('GOOGLE_DRIVE_FOLDER_ID');
|
|
113
|
+
|
|
114
|
+
// Buat backlog
|
|
115
|
+
await artifact.createBacklog('Feature A', 'Description', 'high');
|
|
116
|
+
|
|
117
|
+
// Sync dengan Google Drive
|
|
118
|
+
const result = await artifact.sync();
|
|
119
|
+
console.log(`Added: ${result.added}, Updated: ${result.updated}`);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Configuration
|
|
123
|
+
|
|
124
|
+
### `.sprint-artifact/config.json`
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"version": 1,
|
|
129
|
+
"googleDrive": {
|
|
130
|
+
"folderId": "your-folder-id"
|
|
131
|
+
},
|
|
132
|
+
"selectedTask": "task-id",
|
|
133
|
+
"manifest": {
|
|
134
|
+
"lastSync": "2024-01-01T00:00:00Z",
|
|
135
|
+
"files": []
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### `.sprint-artifact/auth.json`
|
|
141
|
+
|
|
142
|
+
Auto-generated saat login. Jangan commit ke repository.
|
|
143
|
+
|
|
144
|
+
## Project Structure
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
.sprint-artifact/
|
|
148
|
+
├── config.json # Project config (folder ID, manifest)
|
|
149
|
+
└── auth.json # OAuth2 tokens (auto-generated)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Security
|
|
153
|
+
|
|
154
|
+
- `auth.json` dan `credentials.json` di-**gitignore** secara default
|
|
155
|
+
- Setiap user login dengan akun Google masing-masing
|
|
156
|
+
- Token tersimpan lokal di tiap komputer
|
|
157
|
+
- Untuk team, share `credentials.json` via internal docs (bukan public repo)
|
|
158
|
+
|
|
159
|
+
## License
|
|
160
|
+
|
|
161
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { SprintArtifact } from '../sdk/index.js';
|
|
4
|
+
import { resolve } from 'node:path';
|
|
5
|
+
import { login } from '../utils/oauth2.js';
|
|
6
|
+
import { saveAuth } from '../utils/config.js';
|
|
7
|
+
const program = new Command();
|
|
8
|
+
program
|
|
9
|
+
.name('sprint-artifact')
|
|
10
|
+
.description('Sprint Artifact management tool with Google Drive integration')
|
|
11
|
+
.version('0.1.0');
|
|
12
|
+
program
|
|
13
|
+
.command('login')
|
|
14
|
+
.description('Login with Google account (auto-detect credentials)')
|
|
15
|
+
.option('--credentials <path>', 'Path to OAuth2 credentials JSON file')
|
|
16
|
+
.action(async (options) => {
|
|
17
|
+
try {
|
|
18
|
+
const projectRoot = resolve(process.cwd());
|
|
19
|
+
const credentials = await login({
|
|
20
|
+
credentialsPath: options.credentials,
|
|
21
|
+
});
|
|
22
|
+
await saveAuth(projectRoot, {
|
|
23
|
+
type: 'oauth2',
|
|
24
|
+
credentials,
|
|
25
|
+
});
|
|
26
|
+
console.log('✓ Login successful');
|
|
27
|
+
console.log(' Auth saved to .sprint-artifact/auth.json');
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
console.error('✗ Login failed:', error);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
program
|
|
35
|
+
.command('init')
|
|
36
|
+
.description('Initialize a new Sprint Artifact project')
|
|
37
|
+
.requiredOption('--folder-id <id>', 'Google Drive folder ID')
|
|
38
|
+
.option('--auth <path>', 'Path to auth JSON file')
|
|
39
|
+
.action(async (options) => {
|
|
40
|
+
try {
|
|
41
|
+
const projectRoot = resolve(process.cwd());
|
|
42
|
+
const artifact = new SprintArtifact(projectRoot);
|
|
43
|
+
await artifact.init(options.folderId);
|
|
44
|
+
console.log('✓ Sprint Artifact project initialized');
|
|
45
|
+
console.log(` Folder ID: ${options.folderId}`);
|
|
46
|
+
console.log(' Config: .sprint-artifact/config.json');
|
|
47
|
+
if (options.auth) {
|
|
48
|
+
console.log(` Auth: ${options.auth}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.error('✗ Failed to initialize:', error);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
const backlogCmd = program
|
|
57
|
+
.command('backlog')
|
|
58
|
+
.description('Manage backlog items');
|
|
59
|
+
backlogCmd
|
|
60
|
+
.command('create')
|
|
61
|
+
.description('Create a new backlog item')
|
|
62
|
+
.requiredOption('--title <title>', 'Backlog item title')
|
|
63
|
+
.option('--description <desc>', 'Backlog item description', '')
|
|
64
|
+
.option('--priority <priority>', 'Priority (high, medium, low)', 'medium')
|
|
65
|
+
.action(async (options) => {
|
|
66
|
+
try {
|
|
67
|
+
const projectRoot = resolve(process.cwd());
|
|
68
|
+
const artifact = new SprintArtifact(projectRoot);
|
|
69
|
+
const item = await artifact.createBacklog(options.title, options.description, options.priority);
|
|
70
|
+
console.log('✓ Backlog item created');
|
|
71
|
+
console.log(` ID: ${item.id}`);
|
|
72
|
+
console.log(` Title: ${item.title}`);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
console.error('✗ Failed to create backlog item:', error);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
program
|
|
80
|
+
.command('sync')
|
|
81
|
+
.description('Sync documents with Google Drive')
|
|
82
|
+
.action(async () => {
|
|
83
|
+
try {
|
|
84
|
+
const projectRoot = resolve(process.cwd());
|
|
85
|
+
const artifact = new SprintArtifact(projectRoot);
|
|
86
|
+
const result = await artifact.sync();
|
|
87
|
+
console.log('✓ Sync completed');
|
|
88
|
+
console.log(` Added: ${result.added}`);
|
|
89
|
+
console.log(` Updated: ${result.updated}`);
|
|
90
|
+
console.log(` Deleted: ${result.deleted}`);
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.error('✗ Sync failed:', error);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
program
|
|
98
|
+
.command('status')
|
|
99
|
+
.description('Show project status')
|
|
100
|
+
.action(async () => {
|
|
101
|
+
try {
|
|
102
|
+
const projectRoot = resolve(process.cwd());
|
|
103
|
+
const artifact = new SprintArtifact(projectRoot);
|
|
104
|
+
const status = await artifact.status();
|
|
105
|
+
console.log('Sprint Artifact Status');
|
|
106
|
+
console.log('─'.repeat(40));
|
|
107
|
+
console.log(`Initialized: ${status.initialized ? 'Yes' : 'No'}`);
|
|
108
|
+
if (status.initialized) {
|
|
109
|
+
console.log(`Folder ID: ${status.folderId}`);
|
|
110
|
+
console.log(`Selected Task: ${status.selectedTask || 'None'}`);
|
|
111
|
+
console.log(`Last Sync: ${status.lastSync || 'Never'}`);
|
|
112
|
+
console.log(`Files: ${status.fileCount}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.error('✗ Failed to get status:', error);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
program
|
|
121
|
+
.command('select')
|
|
122
|
+
.description('Select a task to work on')
|
|
123
|
+
.argument('<task-id>', 'Task ID to select')
|
|
124
|
+
.action(async (taskId) => {
|
|
125
|
+
try {
|
|
126
|
+
const projectRoot = resolve(process.cwd());
|
|
127
|
+
const artifact = new SprintArtifact(projectRoot);
|
|
128
|
+
await artifact.selectTask(taskId);
|
|
129
|
+
console.log(`✓ Selected task: ${taskId}`);
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
console.error('✗ Failed to select task:', error);
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
const sprintCmd = program
|
|
137
|
+
.command('sprint')
|
|
138
|
+
.description('Manage sprints');
|
|
139
|
+
sprintCmd
|
|
140
|
+
.command('move')
|
|
141
|
+
.description('Move a backlog item to a sprint')
|
|
142
|
+
.requiredOption('--backlog-id <id>', 'Backlog item ID')
|
|
143
|
+
.requiredOption('--sprint-id <id>', 'Sprint ID')
|
|
144
|
+
.action(async (options) => {
|
|
145
|
+
try {
|
|
146
|
+
const projectRoot = resolve(process.cwd());
|
|
147
|
+
const artifact = new SprintArtifact(projectRoot);
|
|
148
|
+
await artifact.moveToSprint(options.backlogId, options.sprintId);
|
|
149
|
+
console.log(`✓ Moved backlog item ${options.backlogId} to sprint ${options.sprintId}`);
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
console.error('✗ Failed to move item:', error);
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
program.parse();
|
|
157
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,180 @@
|
|
|
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 { SprintArtifact } from '../sdk/index.js';
|
|
6
|
+
import { resolve } from 'node:path';
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
const server = new Server({
|
|
9
|
+
name: 'sprint-artifact',
|
|
10
|
+
version: '0.1.0',
|
|
11
|
+
}, {
|
|
12
|
+
capabilities: {
|
|
13
|
+
tools: {},
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
const projectRoot = resolve(process.cwd());
|
|
17
|
+
const artifact = new SprintArtifact(projectRoot);
|
|
18
|
+
const BacklogCreateSchema = z.object({
|
|
19
|
+
title: z.string(),
|
|
20
|
+
description: z.string().optional().default(''),
|
|
21
|
+
priority: z.enum(['high', 'medium', 'low']).optional().default('medium'),
|
|
22
|
+
});
|
|
23
|
+
const SyncSchema = z.object({});
|
|
24
|
+
const MoveToSprintSchema = z.object({
|
|
25
|
+
backlogId: z.string(),
|
|
26
|
+
sprintId: z.string(),
|
|
27
|
+
});
|
|
28
|
+
const StatusSchema = z.object({});
|
|
29
|
+
const SelectTaskSchema = z.object({
|
|
30
|
+
taskId: z.string(),
|
|
31
|
+
});
|
|
32
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
33
|
+
return {
|
|
34
|
+
tools: [
|
|
35
|
+
{
|
|
36
|
+
name: 'backlog_create',
|
|
37
|
+
description: 'Create a new backlog item in Google Drive',
|
|
38
|
+
inputSchema: {
|
|
39
|
+
type: 'object',
|
|
40
|
+
properties: {
|
|
41
|
+
title: { type: 'string', description: 'Backlog item title' },
|
|
42
|
+
description: { type: 'string', description: 'Backlog item description' },
|
|
43
|
+
priority: {
|
|
44
|
+
type: 'string',
|
|
45
|
+
enum: ['high', 'medium', 'low'],
|
|
46
|
+
description: 'Priority level',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
required: ['title'],
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'sync_documents',
|
|
54
|
+
description: 'Sync documents between local and Google Drive',
|
|
55
|
+
inputSchema: {
|
|
56
|
+
type: 'object',
|
|
57
|
+
properties: {},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: 'move_to_sprint',
|
|
62
|
+
description: 'Move a backlog item to a sprint',
|
|
63
|
+
inputSchema: {
|
|
64
|
+
type: 'object',
|
|
65
|
+
properties: {
|
|
66
|
+
backlogId: { type: 'string', description: 'Backlog item ID' },
|
|
67
|
+
sprintId: { type: 'string', description: 'Sprint ID' },
|
|
68
|
+
},
|
|
69
|
+
required: ['backlogId', 'sprintId'],
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: 'status',
|
|
74
|
+
description: 'Get current project status',
|
|
75
|
+
inputSchema: {
|
|
76
|
+
type: 'object',
|
|
77
|
+
properties: {},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: 'select_task',
|
|
82
|
+
description: 'Select a task to work on',
|
|
83
|
+
inputSchema: {
|
|
84
|
+
type: 'object',
|
|
85
|
+
properties: {
|
|
86
|
+
taskId: { type: 'string', description: 'Task ID to select' },
|
|
87
|
+
},
|
|
88
|
+
required: ['taskId'],
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
95
|
+
const { name, arguments: args } = request.params;
|
|
96
|
+
try {
|
|
97
|
+
switch (name) {
|
|
98
|
+
case 'backlog_create': {
|
|
99
|
+
const { title, description, priority } = BacklogCreateSchema.parse(args);
|
|
100
|
+
const item = await artifact.createBacklog(title, description, priority);
|
|
101
|
+
return {
|
|
102
|
+
content: [
|
|
103
|
+
{
|
|
104
|
+
type: 'text',
|
|
105
|
+
text: JSON.stringify(item, null, 2),
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
case 'sync_documents': {
|
|
111
|
+
SyncSchema.parse(args);
|
|
112
|
+
const result = await artifact.sync();
|
|
113
|
+
return {
|
|
114
|
+
content: [
|
|
115
|
+
{
|
|
116
|
+
type: 'text',
|
|
117
|
+
text: JSON.stringify(result, null, 2),
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
case 'move_to_sprint': {
|
|
123
|
+
const { backlogId, sprintId } = MoveToSprintSchema.parse(args);
|
|
124
|
+
await artifact.moveToSprint(backlogId, sprintId);
|
|
125
|
+
return {
|
|
126
|
+
content: [
|
|
127
|
+
{
|
|
128
|
+
type: 'text',
|
|
129
|
+
text: `Moved backlog item ${backlogId} to sprint ${sprintId}`,
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
case 'status': {
|
|
135
|
+
StatusSchema.parse(args);
|
|
136
|
+
const status = await artifact.status();
|
|
137
|
+
return {
|
|
138
|
+
content: [
|
|
139
|
+
{
|
|
140
|
+
type: 'text',
|
|
141
|
+
text: JSON.stringify(status, null, 2),
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
case 'select_task': {
|
|
147
|
+
const { taskId } = SelectTaskSchema.parse(args);
|
|
148
|
+
await artifact.selectTask(taskId);
|
|
149
|
+
return {
|
|
150
|
+
content: [
|
|
151
|
+
{
|
|
152
|
+
type: 'text',
|
|
153
|
+
text: `Selected task: ${taskId}`,
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
default:
|
|
159
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
return {
|
|
164
|
+
content: [
|
|
165
|
+
{
|
|
166
|
+
type: 'text',
|
|
167
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
isError: true,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
async function main() {
|
|
175
|
+
const transport = new StdioServerTransport();
|
|
176
|
+
await server.connect(transport);
|
|
177
|
+
console.error('Sprint Artifact MCP server running on stdio');
|
|
178
|
+
}
|
|
179
|
+
main().catch(console.error);
|
|
180
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AuthConfig, ManifestFile } from '../types/index.js';
|
|
2
|
+
export declare class GoogleDriveClient {
|
|
3
|
+
private drive;
|
|
4
|
+
constructor(auth: AuthConfig);
|
|
5
|
+
private createAuthClient;
|
|
6
|
+
createFolder(name: string, parentId?: string): Promise<string>;
|
|
7
|
+
createFile(name: string, content: string, parentId?: string, mimeType?: string): Promise<string>;
|
|
8
|
+
getFile(fileId: string): Promise<string>;
|
|
9
|
+
updateFile(fileId: string, content: string, mimeType?: string): Promise<void>;
|
|
10
|
+
listFiles(folderId: string): Promise<ManifestFile[]>;
|
|
11
|
+
getFileMetadata(fileId: string): Promise<ManifestFile>;
|
|
12
|
+
deleteFile(fileId: string): Promise<void>;
|
|
13
|
+
findFolder(name: string, parentId?: string): Promise<string | null>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=google-drive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google-drive.d.ts","sourceRoot":"","sources":["../../src/sdk/google-drive.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAqB,MAAM,mBAAmB,CAAC;AAErF,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,KAAK,CAAiB;gBAElB,IAAI,EAAE,UAAU;IAK5B,OAAO,CAAC,gBAAgB;IAuBlB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAe9D,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,SAAkB,GAAG,OAAO,CAAC,MAAM,CAAC;IAoBzG,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQxC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,SAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtF,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAgBpD,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAgBtD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzC,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAa1E"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { google } from 'googleapis';
|
|
2
|
+
export class GoogleDriveClient {
|
|
3
|
+
drive;
|
|
4
|
+
constructor(auth) {
|
|
5
|
+
const authClient = this.createAuthClient(auth);
|
|
6
|
+
this.drive = google.drive({ version: 'v3', auth: authClient });
|
|
7
|
+
}
|
|
8
|
+
createAuthClient(auth) {
|
|
9
|
+
if (auth.type === 'service_account') {
|
|
10
|
+
return new google.auth.GoogleAuth({
|
|
11
|
+
credentials: auth.credentials,
|
|
12
|
+
scopes: ['https://www.googleapis.com/auth/drive'],
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
const creds = auth.credentials;
|
|
17
|
+
const oauth2Client = new google.auth.OAuth2(creds.client_id, creds.client_secret, creds.redirect_uris[0]);
|
|
18
|
+
if (creds.refresh_token) {
|
|
19
|
+
oauth2Client.setCredentials({
|
|
20
|
+
refresh_token: creds.refresh_token,
|
|
21
|
+
access_token: creds.access_token,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
return oauth2Client;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async createFolder(name, parentId) {
|
|
28
|
+
const fileMetadata = {
|
|
29
|
+
name,
|
|
30
|
+
mimeType: 'application/vnd.google-apps.folder',
|
|
31
|
+
...(parentId && { parents: [parentId] }),
|
|
32
|
+
};
|
|
33
|
+
const response = await this.drive.files.create({
|
|
34
|
+
requestBody: fileMetadata,
|
|
35
|
+
fields: 'id',
|
|
36
|
+
});
|
|
37
|
+
return response.data.id;
|
|
38
|
+
}
|
|
39
|
+
async createFile(name, content, parentId, mimeType = 'text/markdown') {
|
|
40
|
+
const fileMetadata = {
|
|
41
|
+
name,
|
|
42
|
+
...(parentId && { parents: [parentId] }),
|
|
43
|
+
};
|
|
44
|
+
const media = {
|
|
45
|
+
mimeType,
|
|
46
|
+
body: content,
|
|
47
|
+
};
|
|
48
|
+
const response = await this.drive.files.create({
|
|
49
|
+
requestBody: fileMetadata,
|
|
50
|
+
media,
|
|
51
|
+
fields: 'id',
|
|
52
|
+
});
|
|
53
|
+
return response.data.id;
|
|
54
|
+
}
|
|
55
|
+
async getFile(fileId) {
|
|
56
|
+
const response = await this.drive.files.get({
|
|
57
|
+
fileId,
|
|
58
|
+
alt: 'media',
|
|
59
|
+
});
|
|
60
|
+
return response.data;
|
|
61
|
+
}
|
|
62
|
+
async updateFile(fileId, content, mimeType = 'text/markdown') {
|
|
63
|
+
await this.drive.files.update({
|
|
64
|
+
fileId,
|
|
65
|
+
media: {
|
|
66
|
+
mimeType,
|
|
67
|
+
body: content,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
async listFiles(folderId) {
|
|
72
|
+
const response = await this.drive.files.list({
|
|
73
|
+
q: `'${folderId}' in parents and trashed = false`,
|
|
74
|
+
fields: 'files(id, name, mimeType, modifiedTime, md5Checksum)',
|
|
75
|
+
pageSize: 1000,
|
|
76
|
+
});
|
|
77
|
+
return (response.data.files || []).map((file) => ({
|
|
78
|
+
id: file.id,
|
|
79
|
+
name: file.name,
|
|
80
|
+
mimeType: file.mimeType,
|
|
81
|
+
modifiedTime: file.modifiedTime,
|
|
82
|
+
md5Checksum: file.md5Checksum || undefined,
|
|
83
|
+
}));
|
|
84
|
+
}
|
|
85
|
+
async getFileMetadata(fileId) {
|
|
86
|
+
const response = await this.drive.files.get({
|
|
87
|
+
fileId,
|
|
88
|
+
fields: 'id, name, mimeType, modifiedTime, md5Checksum',
|
|
89
|
+
});
|
|
90
|
+
const file = response.data;
|
|
91
|
+
return {
|
|
92
|
+
id: file.id,
|
|
93
|
+
name: file.name,
|
|
94
|
+
mimeType: file.mimeType,
|
|
95
|
+
modifiedTime: file.modifiedTime,
|
|
96
|
+
md5Checksum: file.md5Checksum || undefined,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
async deleteFile(fileId) {
|
|
100
|
+
await this.drive.files.delete({ fileId });
|
|
101
|
+
}
|
|
102
|
+
async findFolder(name, parentId) {
|
|
103
|
+
const query = parentId
|
|
104
|
+
? `name = '${name}' and '${parentId}' in parents and mimeType = 'application/vnd.google-apps.folder' and trashed = false`
|
|
105
|
+
: `name = '${name}' and mimeType = 'application/vnd.google-apps.folder' and trashed = false`;
|
|
106
|
+
const response = await this.drive.files.list({
|
|
107
|
+
q: query,
|
|
108
|
+
fields: 'files(id)',
|
|
109
|
+
pageSize: 1,
|
|
110
|
+
});
|
|
111
|
+
return response.data.files?.[0]?.id || null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=google-drive.js.map
|