@pollychrome/joan-mcp 1.0.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 +385 -0
- package/bin/joan-mcp +16 -0
- package/dist/auth.d.ts +49 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +264 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +326 -0
- package/dist/cli.js.map +1 -0
- package/dist/client/api-client.d.ts +86 -0
- package/dist/client/api-client.d.ts.map +1 -0
- package/dist/client/api-client.js +182 -0
- package/dist/client/api-client.js.map +1 -0
- package/dist/client/types.d.ts +270 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +5 -0
- package/dist/client/types.js.map +1 -0
- package/dist/config.d.ts +33 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +71 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +118 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/goals.d.ts +7 -0
- package/dist/resources/goals.d.ts.map +1 -0
- package/dist/resources/goals.js +49 -0
- package/dist/resources/goals.js.map +1 -0
- package/dist/resources/index.d.ts +16 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +20 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/milestones.d.ts +7 -0
- package/dist/resources/milestones.d.ts.map +1 -0
- package/dist/resources/milestones.js +40 -0
- package/dist/resources/milestones.js.map +1 -0
- package/dist/resources/notes.d.ts +7 -0
- package/dist/resources/notes.d.ts.map +1 -0
- package/dist/resources/notes.js +33 -0
- package/dist/resources/notes.js.map +1 -0
- package/dist/resources/projects.d.ts +7 -0
- package/dist/resources/projects.d.ts.map +1 -0
- package/dist/resources/projects.js +97 -0
- package/dist/resources/projects.js.map +1 -0
- package/dist/resources/tasks.d.ts +7 -0
- package/dist/resources/tasks.d.ts.map +1 -0
- package/dist/resources/tasks.js +36 -0
- package/dist/resources/tasks.js.map +1 -0
- package/dist/tools/goals.d.ts +7 -0
- package/dist/tools/goals.d.ts.map +1 -0
- package/dist/tools/goals.js +114 -0
- package/dist/tools/goals.js.map +1 -0
- package/dist/tools/index.d.ts +16 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +20 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/milestones.d.ts +7 -0
- package/dist/tools/milestones.d.ts.map +1 -0
- package/dist/tools/milestones.js +119 -0
- package/dist/tools/milestones.js.map +1 -0
- package/dist/tools/notes.d.ts +7 -0
- package/dist/tools/notes.d.ts.map +1 -0
- package/dist/tools/notes.js +82 -0
- package/dist/tools/notes.js.map +1 -0
- package/dist/tools/projects.d.ts +7 -0
- package/dist/tools/projects.d.ts.map +1 -0
- package/dist/tools/projects.js +63 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/tasks.d.ts +7 -0
- package/dist/tools/tasks.d.ts.map +1 -0
- package/dist/tools/tasks.js +125 -0
- package/dist/tools/tasks.js.map +1 -0
- package/dist/utils/converters.d.ts +78 -0
- package/dist/utils/converters.d.ts.map +1 -0
- package/dist/utils/converters.js +79 -0
- package/dist/utils/converters.js.map +1 -0
- package/dist/utils/errors.d.ts +27 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +104 -0
- package/dist/utils/errors.js.map +1 -0
- package/package.json +53 -0
package/dist/config.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration management for Joan MCP server
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { getAuthToken } from './auth.js';
|
|
6
|
+
import { ConfigurationError } from './utils/errors.js';
|
|
7
|
+
const ConfigSchema = z.object({
|
|
8
|
+
apiUrl: z.string().url(),
|
|
9
|
+
authToken: z.string().min(1),
|
|
10
|
+
});
|
|
11
|
+
const DEFAULT_API_URL = 'https://joan-api.alexbbenson.workers.dev/api/v1';
|
|
12
|
+
/**
|
|
13
|
+
* Load configuration from environment and stored credentials
|
|
14
|
+
*/
|
|
15
|
+
export async function loadConfig() {
|
|
16
|
+
const apiUrl = process.env.JOAN_API_URL || DEFAULT_API_URL;
|
|
17
|
+
let authToken;
|
|
18
|
+
try {
|
|
19
|
+
authToken = await getAuthToken();
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
throw new ConfigurationError('No authentication token found. Run "joan-mcp login" to authenticate or set JOAN_AUTH_TOKEN environment variable.');
|
|
23
|
+
}
|
|
24
|
+
const config = {
|
|
25
|
+
apiUrl,
|
|
26
|
+
authToken,
|
|
27
|
+
};
|
|
28
|
+
try {
|
|
29
|
+
return ConfigSchema.parse(config);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
if (error instanceof z.ZodError) {
|
|
33
|
+
const issues = error.issues.map(i => `${i.path.join('.')}: ${i.message}`).join(', ');
|
|
34
|
+
throw new ConfigurationError(`Invalid configuration: ${issues}`);
|
|
35
|
+
}
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get the API URL (for display purposes, without needing full config)
|
|
41
|
+
*/
|
|
42
|
+
export function getApiUrl() {
|
|
43
|
+
return process.env.JOAN_API_URL || DEFAULT_API_URL;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get the base app URL (for login redirects)
|
|
47
|
+
*/
|
|
48
|
+
export function getAppUrl() {
|
|
49
|
+
const apiUrl = getApiUrl();
|
|
50
|
+
// Convert API URL to app URL
|
|
51
|
+
if (apiUrl.includes('joan-api.alexbbenson.workers.dev')) {
|
|
52
|
+
return 'https://joan.nintai.app';
|
|
53
|
+
}
|
|
54
|
+
if (apiUrl.includes('joan-api-staging')) {
|
|
55
|
+
return 'https://staging.joan.nintai.app';
|
|
56
|
+
}
|
|
57
|
+
// Local development
|
|
58
|
+
if (apiUrl.includes('localhost:8787')) {
|
|
59
|
+
return 'http://localhost:5174';
|
|
60
|
+
}
|
|
61
|
+
// Default to production
|
|
62
|
+
return 'https://joan.nintai.app';
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get the MCP auth URL (for CLI login flow)
|
|
66
|
+
*/
|
|
67
|
+
export function getMcpAuthUrl(port) {
|
|
68
|
+
const appUrl = getAppUrl();
|
|
69
|
+
return `${appUrl}/mcp-auth?port=${port}`;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACxB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC7B,CAAC,CAAC;AAIH,MAAM,eAAe,GAAG,iDAAiD,CAAC;AAE1E;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,eAAe,CAAC;IAE3D,IAAI,SAAiB,CAAC;IACtB,IAAI,CAAC;QACH,SAAS,GAAG,MAAM,YAAY,EAAE,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,kBAAkB,CAC1B,kHAAkH,CACnH,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG;QACb,MAAM;QACN,SAAS;KACV,CAAC;IAEF,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,CAAC,CAAC,QAAQ,EAAE,CAAC;YAChC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACrF,MAAM,IAAI,kBAAkB,CAAC,0BAA0B,MAAM,EAAE,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,eAAe,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS;IACvB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,6BAA6B;IAC7B,IAAI,MAAM,CAAC,QAAQ,CAAC,kCAAkC,CAAC,EAAE,CAAC;QACxD,OAAO,yBAAyB,CAAC;IACnC,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACxC,OAAO,iCAAiC,CAAC;IAC3C,CAAC;IACD,oBAAoB;IACpB,IAAI,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACtC,OAAO,uBAAuB,CAAC;IACjC,CAAC;IACD,wBAAwB;IACxB,OAAO,yBAAyB,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,OAAO,GAAG,MAAM,kBAAkB,IAAI,EAAE,CAAC;AAC3C,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Joan MCP Server - Entry Point
|
|
3
|
+
*
|
|
4
|
+
* This MCP server enables AI assistants like Claude to interact with
|
|
5
|
+
* Joan productivity app features including Projects, Tasks, Goals,
|
|
6
|
+
* Milestones, and Notes.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Start the MCP server
|
|
10
|
+
*/
|
|
11
|
+
export declare function startServer(): Promise<void>;
|
|
12
|
+
export { loadConfig } from './config.js';
|
|
13
|
+
export { JoanApiClient } from './client/api-client.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA4EH;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CA0CjD;AAGD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Joan MCP Server - Entry Point
|
|
3
|
+
*
|
|
4
|
+
* This MCP server enables AI assistants like Claude to interact with
|
|
5
|
+
* Joan productivity app features including Projects, Tasks, Goals,
|
|
6
|
+
* Milestones, and Notes.
|
|
7
|
+
*/
|
|
8
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
9
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
10
|
+
import { loadConfig } from './config.js';
|
|
11
|
+
import { JoanApiClient } from './client/api-client.js';
|
|
12
|
+
import { registerAllTools } from './tools/index.js';
|
|
13
|
+
import { registerAllResources } from './resources/index.js';
|
|
14
|
+
const SERVER_NAME = 'joan-mcp';
|
|
15
|
+
const SERVER_VERSION = '1.0.0';
|
|
16
|
+
/**
|
|
17
|
+
* Server instructions that describe Joan MCP to AI assistants.
|
|
18
|
+
* These are automatically sent to clients during initialization.
|
|
19
|
+
*/
|
|
20
|
+
const SERVER_INSTRUCTIONS = `
|
|
21
|
+
Joan is a productivity application for managing projects, tasks, goals, milestones, and notes. This MCP server enables you to interact with the user's Joan data.
|
|
22
|
+
|
|
23
|
+
## Available Tools (Write Operations)
|
|
24
|
+
|
|
25
|
+
### Tasks
|
|
26
|
+
- create_task: Create a new task in a project (requires project_id, title; optional: description, status, priority, due_date, column_id)
|
|
27
|
+
- update_task: Update task properties (title, description, status, priority, due_date, column_id)
|
|
28
|
+
- complete_task: Mark a task as completed
|
|
29
|
+
- delete_task: Delete a task
|
|
30
|
+
|
|
31
|
+
### Projects
|
|
32
|
+
- create_project: Create a new project (name required; optional: description, status, start_date, end_date)
|
|
33
|
+
- update_project: Update project properties
|
|
34
|
+
|
|
35
|
+
### Milestones
|
|
36
|
+
- create_milestone: Create a milestone in a project (requires project_id, title; optional: description, target_date)
|
|
37
|
+
- update_milestone: Update milestone details
|
|
38
|
+
- delete_milestone: Delete a milestone
|
|
39
|
+
- link_tasks_to_milestone: Associate tasks with a milestone
|
|
40
|
+
- unlink_task_from_milestone: Remove a task from a milestone
|
|
41
|
+
|
|
42
|
+
### Goals
|
|
43
|
+
- create_goal: Create a new goal (title required; optional: description, target_date, status)
|
|
44
|
+
- update_goal: Update goal progress or details
|
|
45
|
+
- delete_goal: Delete a goal
|
|
46
|
+
- link_task_to_goal: Link a task to track goal progress
|
|
47
|
+
- unlink_task_from_goal: Remove task from goal tracking
|
|
48
|
+
|
|
49
|
+
### Notes
|
|
50
|
+
- create_note: Create a new note (title required; optional: content, tags)
|
|
51
|
+
- update_note: Update note content or metadata
|
|
52
|
+
- delete_note: Delete a note
|
|
53
|
+
|
|
54
|
+
## Available Resources (Read Operations)
|
|
55
|
+
|
|
56
|
+
Use these URIs to read Joan data:
|
|
57
|
+
- joan://projects - List all projects
|
|
58
|
+
- joan://projects/{id} - Get project details with stats
|
|
59
|
+
- joan://projects/{id}/tasks - Get tasks in a project
|
|
60
|
+
- joan://projects/{id}/milestones - Get project milestones
|
|
61
|
+
- joan://projects/{id}/columns - Get kanban columns
|
|
62
|
+
- joan://tasks - List all tasks
|
|
63
|
+
- joan://tasks/{id} - Get task details
|
|
64
|
+
- joan://goals - List all goals
|
|
65
|
+
- joan://goals/{id} - Get goal with linked tasks
|
|
66
|
+
- joan://notes - List all notes
|
|
67
|
+
- joan://notes/{id} - Get note details
|
|
68
|
+
|
|
69
|
+
## Usage Guidelines
|
|
70
|
+
|
|
71
|
+
1. When the user mentions tasks, projects, goals, or productivity tracking, consider using Joan tools
|
|
72
|
+
2. Always read relevant resources first to get context (e.g., list projects before creating a task)
|
|
73
|
+
3. Task status values: "todo", "in_progress", "done", "blocked"
|
|
74
|
+
4. Task priority values: "low", "medium", "high", "urgent"
|
|
75
|
+
5. Project status values: "planning", "active", "on_hold", "completed", "archived"
|
|
76
|
+
6. Goal status values: "not_started", "in_progress", "completed", "abandoned"
|
|
77
|
+
`.trim();
|
|
78
|
+
/**
|
|
79
|
+
* Start the MCP server
|
|
80
|
+
*/
|
|
81
|
+
export async function startServer() {
|
|
82
|
+
// Load configuration
|
|
83
|
+
const config = await loadConfig();
|
|
84
|
+
// Initialize API client
|
|
85
|
+
const apiClient = new JoanApiClient({
|
|
86
|
+
baseUrl: config.apiUrl,
|
|
87
|
+
authToken: config.authToken,
|
|
88
|
+
});
|
|
89
|
+
// Verify auth token works
|
|
90
|
+
try {
|
|
91
|
+
await apiClient.getCurrentUser();
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
console.error('Failed to verify authentication. Please check your token.');
|
|
95
|
+
console.error('Run "joan-mcp login" to authenticate or set JOAN_AUTH_TOKEN.');
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
// Create MCP server with instructions for AI assistants
|
|
99
|
+
const server = new McpServer({
|
|
100
|
+
name: SERVER_NAME,
|
|
101
|
+
version: SERVER_VERSION,
|
|
102
|
+
}, {
|
|
103
|
+
instructions: SERVER_INSTRUCTIONS,
|
|
104
|
+
});
|
|
105
|
+
// Register all tools (write operations)
|
|
106
|
+
registerAllTools(server, apiClient);
|
|
107
|
+
// Register all resources (read operations)
|
|
108
|
+
registerAllResources(server, apiClient);
|
|
109
|
+
// Connect via stdio transport
|
|
110
|
+
const transport = new StdioServerTransport();
|
|
111
|
+
await server.connect(transport);
|
|
112
|
+
// Log to stderr so it doesn't interfere with MCP protocol
|
|
113
|
+
console.error(`${SERVER_NAME} v${SERVER_VERSION} started`);
|
|
114
|
+
}
|
|
115
|
+
// Export for CLI
|
|
116
|
+
export { loadConfig } from './config.js';
|
|
117
|
+
export { JoanApiClient } from './client/api-client.js';
|
|
118
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,WAAW,GAAG,UAAU,CAAC;AAC/B,MAAM,cAAc,GAAG,OAAO,CAAC;AAE/B;;;GAGG;AACH,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyD3B,CAAC,IAAI,EAAE,CAAC;AAGT;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,qBAAqB;IACrB,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;IAElC,wBAAwB;IACxB,MAAM,SAAS,GAAG,IAAI,aAAa,CAAC;QAClC,OAAO,EAAE,MAAM,CAAC,MAAM;QACtB,SAAS,EAAE,MAAM,CAAC,SAAS;KAC5B,CAAC,CAAC;IAEH,0BAA0B;IAC1B,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,cAAc,EAAE,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAC3E,OAAO,CAAC,KAAK,CAAC,8DAA8D,CAAC,CAAC;QAC9E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,wDAAwD;IACxD,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;QACE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,cAAc;KACxB,EACD;QACE,YAAY,EAAE,mBAAmB;KAClC,CACF,CAAC;IAEF,wCAAwC;IACxC,gBAAgB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAEpC,2CAA2C;IAC3C,oBAAoB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAExC,8BAA8B;IAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,0DAA0D;IAC1D,OAAO,CAAC,KAAK,CAAC,GAAG,WAAW,KAAK,cAAc,UAAU,CAAC,CAAC;AAC7D,CAAC;AAED,iBAAiB;AACjB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP resources for goal data
|
|
3
|
+
*/
|
|
4
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
import type { JoanApiClient } from '../client/api-client.js';
|
|
6
|
+
export declare function registerGoalResources(server: McpServer, client: JoanApiClient): void;
|
|
7
|
+
//# sourceMappingURL=goals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"goals.d.ts","sourceRoot":"","sources":["../../src/resources/goals.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAiEpF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP resources for goal data
|
|
3
|
+
*/
|
|
4
|
+
export function registerGoalResources(server, client) {
|
|
5
|
+
// List all goals
|
|
6
|
+
server.resource('joan://goals', 'List all goals', async () => {
|
|
7
|
+
const goals = await client.listGoals({ include_tasks: true });
|
|
8
|
+
return {
|
|
9
|
+
contents: [{
|
|
10
|
+
uri: 'joan://goals',
|
|
11
|
+
mimeType: 'application/json',
|
|
12
|
+
text: JSON.stringify(goals, null, 2),
|
|
13
|
+
}],
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
// Goal details resource template
|
|
17
|
+
server.resource('joan://goals/{goalId}', 'Get detailed information about a specific goal including linked tasks', async (uri) => {
|
|
18
|
+
const match = uri.pathname.match(/^\/\/goals\/([^/]+)$/);
|
|
19
|
+
const goalId = match?.[1];
|
|
20
|
+
if (!goalId) {
|
|
21
|
+
throw new Error('Invalid goal URI');
|
|
22
|
+
}
|
|
23
|
+
const goal = await client.getGoal(goalId);
|
|
24
|
+
return {
|
|
25
|
+
contents: [{
|
|
26
|
+
uri: uri.toString(),
|
|
27
|
+
mimeType: 'application/json',
|
|
28
|
+
text: JSON.stringify(goal, null, 2),
|
|
29
|
+
}],
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
// Goal stats resource template
|
|
33
|
+
server.resource('joan://goals/{goalId}/stats', 'Get statistics for a specific goal', async (uri) => {
|
|
34
|
+
const match = uri.pathname.match(/^\/\/goals\/([^/]+)\/stats$/);
|
|
35
|
+
const goalId = match?.[1];
|
|
36
|
+
if (!goalId) {
|
|
37
|
+
throw new Error('Invalid goal stats URI');
|
|
38
|
+
}
|
|
39
|
+
const stats = await client.getGoalStats(goalId);
|
|
40
|
+
return {
|
|
41
|
+
contents: [{
|
|
42
|
+
uri: uri.toString(),
|
|
43
|
+
mimeType: 'application/json',
|
|
44
|
+
text: JSON.stringify(stats, null, 2),
|
|
45
|
+
}],
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=goals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"goals.js","sourceRoot":"","sources":["../../src/resources/goals.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,UAAU,qBAAqB,CAAC,MAAiB,EAAE,MAAqB;IAC5E,iBAAiB;IACjB,MAAM,CAAC,QAAQ,CACb,cAAc,EACd,gBAAgB,EAChB,KAAK,IAAI,EAAE;QACT,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAE9D,OAAO;YACL,QAAQ,EAAE,CAAC;oBACT,GAAG,EAAE,cAAc;oBACnB,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;iBACrC,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,iCAAiC;IACjC,MAAM,CAAC,QAAQ,CACb,uBAAuB,EACvB,uEAAuE,EACvE,KAAK,EAAE,GAAG,EAAE,EAAE;QACZ,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QAE1B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACtC,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAE1C,OAAO;YACL,QAAQ,EAAE,CAAC;oBACT,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE;oBACnB,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;iBACpC,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,+BAA+B;IAC/B,MAAM,CAAC,QAAQ,CACb,6BAA6B,EAC7B,oCAAoC,EACpC,KAAK,EAAE,GAAG,EAAE,EAAE;QACZ,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAChE,MAAM,MAAM,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QAE1B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAEhD,OAAO;YACL,QAAQ,EAAE,CAAC;oBACT,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE;oBACnB,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;iBACrC,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource registration for Joan MCP server
|
|
3
|
+
*/
|
|
4
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
import type { JoanApiClient } from '../client/api-client.js';
|
|
6
|
+
import { registerProjectResources } from './projects.js';
|
|
7
|
+
import { registerTaskResources } from './tasks.js';
|
|
8
|
+
import { registerMilestoneResources } from './milestones.js';
|
|
9
|
+
import { registerGoalResources } from './goals.js';
|
|
10
|
+
import { registerNoteResources } from './notes.js';
|
|
11
|
+
/**
|
|
12
|
+
* Register all resources with the MCP server
|
|
13
|
+
*/
|
|
14
|
+
export declare function registerAllResources(server: McpServer, client: JoanApiClient): void;
|
|
15
|
+
export { registerProjectResources, registerTaskResources, registerMilestoneResources, registerGoalResources, registerNoteResources, };
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEnD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAMnF;AAED,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,GACtB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource registration for Joan MCP server
|
|
3
|
+
*/
|
|
4
|
+
import { registerProjectResources } from './projects.js';
|
|
5
|
+
import { registerTaskResources } from './tasks.js';
|
|
6
|
+
import { registerMilestoneResources } from './milestones.js';
|
|
7
|
+
import { registerGoalResources } from './goals.js';
|
|
8
|
+
import { registerNoteResources } from './notes.js';
|
|
9
|
+
/**
|
|
10
|
+
* Register all resources with the MCP server
|
|
11
|
+
*/
|
|
12
|
+
export function registerAllResources(server, client) {
|
|
13
|
+
registerProjectResources(server, client);
|
|
14
|
+
registerTaskResources(server, client);
|
|
15
|
+
registerMilestoneResources(server, client);
|
|
16
|
+
registerGoalResources(server, client);
|
|
17
|
+
registerNoteResources(server, client);
|
|
18
|
+
}
|
|
19
|
+
export { registerProjectResources, registerTaskResources, registerMilestoneResources, registerGoalResources, registerNoteResources, };
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEnD;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,MAAqB;IAC3E,wBAAwB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,0BAA0B,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACxC,CAAC;AAED,OAAO,EACL,wBAAwB,EACxB,qBAAqB,EACrB,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,GACtB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP resources for milestone data
|
|
3
|
+
*/
|
|
4
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
import type { JoanApiClient } from '../client/api-client.js';
|
|
6
|
+
export declare function registerMilestoneResources(server: McpServer, client: JoanApiClient): void;
|
|
7
|
+
//# sourceMappingURL=milestones.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"milestones.d.ts","sourceRoot":"","sources":["../../src/resources/milestones.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAkDzF"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP resources for milestone data
|
|
3
|
+
*/
|
|
4
|
+
export function registerMilestoneResources(server, client) {
|
|
5
|
+
// Milestone details resource template (requires project context)
|
|
6
|
+
server.resource('joan://projects/{projectId}/milestones/{milestoneId}', 'Get detailed information about a specific milestone including linked tasks', async (uri) => {
|
|
7
|
+
const match = uri.pathname.match(/^\/\/projects\/([^/]+)\/milestones\/([^/]+)$/);
|
|
8
|
+
const projectId = match?.[1];
|
|
9
|
+
const milestoneId = match?.[2];
|
|
10
|
+
if (!projectId || !milestoneId) {
|
|
11
|
+
throw new Error('Invalid milestone URI');
|
|
12
|
+
}
|
|
13
|
+
const milestone = await client.getMilestone(projectId, milestoneId);
|
|
14
|
+
return {
|
|
15
|
+
contents: [{
|
|
16
|
+
uri: uri.toString(),
|
|
17
|
+
mimeType: 'application/json',
|
|
18
|
+
text: JSON.stringify(milestone, null, 2),
|
|
19
|
+
}],
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
// Milestone resources
|
|
23
|
+
server.resource('joan://projects/{projectId}/milestones/{milestoneId}/resources', 'Get resources (links and notes) attached to a milestone', async (uri) => {
|
|
24
|
+
const match = uri.pathname.match(/^\/\/projects\/([^/]+)\/milestones\/([^/]+)\/resources$/);
|
|
25
|
+
const projectId = match?.[1];
|
|
26
|
+
const milestoneId = match?.[2];
|
|
27
|
+
if (!projectId || !milestoneId) {
|
|
28
|
+
throw new Error('Invalid milestone resources URI');
|
|
29
|
+
}
|
|
30
|
+
const resources = await client.getMilestoneResources(projectId, milestoneId);
|
|
31
|
+
return {
|
|
32
|
+
contents: [{
|
|
33
|
+
uri: uri.toString(),
|
|
34
|
+
mimeType: 'application/json',
|
|
35
|
+
text: JSON.stringify(resources, null, 2),
|
|
36
|
+
}],
|
|
37
|
+
};
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=milestones.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"milestones.js","sourceRoot":"","sources":["../../src/resources/milestones.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,UAAU,0BAA0B,CAAC,MAAiB,EAAE,MAAqB;IACjF,iEAAiE;IACjE,MAAM,CAAC,QAAQ,CACb,sDAAsD,EACtD,4EAA4E,EAC5E,KAAK,EAAE,GAAG,EAAE,EAAE;QACZ,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;QACjF,MAAM,SAAS,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7B,MAAM,WAAW,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QAE/B,IAAI,CAAC,SAAS,IAAI,CAAC,WAAW,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC3C,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QAEpE,OAAO;YACL,QAAQ,EAAE,CAAC;oBACT,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE;oBACnB,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;iBACzC,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,sBAAsB;IACtB,MAAM,CAAC,QAAQ,CACb,gEAAgE,EAChE,yDAAyD,EACzD,KAAK,EAAE,GAAG,EAAE,EAAE;QACZ,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;QAC5F,MAAM,SAAS,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7B,MAAM,WAAW,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QAE/B,IAAI,CAAC,SAAS,IAAI,CAAC,WAAW,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QAE7E,OAAO;YACL,QAAQ,EAAE,CAAC;oBACT,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE;oBACnB,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;iBACzC,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP resources for note data
|
|
3
|
+
*/
|
|
4
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
import type { JoanApiClient } from '../client/api-client.js';
|
|
6
|
+
export declare function registerNoteResources(server: McpServer, client: JoanApiClient): void;
|
|
7
|
+
//# sourceMappingURL=notes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notes.d.ts","sourceRoot":"","sources":["../../src/resources/notes.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAyCpF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP resources for note data
|
|
3
|
+
*/
|
|
4
|
+
export function registerNoteResources(server, client) {
|
|
5
|
+
// List all notes
|
|
6
|
+
server.resource('joan://notes', 'List all notes', async () => {
|
|
7
|
+
const notes = await client.listNotes();
|
|
8
|
+
return {
|
|
9
|
+
contents: [{
|
|
10
|
+
uri: 'joan://notes',
|
|
11
|
+
mimeType: 'application/json',
|
|
12
|
+
text: JSON.stringify(notes, null, 2),
|
|
13
|
+
}],
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
// Note details resource template
|
|
17
|
+
server.resource('joan://notes/{noteId}', 'Get detailed information about a specific note', async (uri) => {
|
|
18
|
+
const match = uri.pathname.match(/^\/\/notes\/([^/]+)$/);
|
|
19
|
+
const noteId = match?.[1];
|
|
20
|
+
if (!noteId) {
|
|
21
|
+
throw new Error('Invalid note URI');
|
|
22
|
+
}
|
|
23
|
+
const note = await client.getNote(noteId);
|
|
24
|
+
return {
|
|
25
|
+
contents: [{
|
|
26
|
+
uri: uri.toString(),
|
|
27
|
+
mimeType: 'application/json',
|
|
28
|
+
text: JSON.stringify(note, null, 2),
|
|
29
|
+
}],
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=notes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notes.js","sourceRoot":"","sources":["../../src/resources/notes.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,MAAM,UAAU,qBAAqB,CAAC,MAAiB,EAAE,MAAqB;IAC5E,iBAAiB;IACjB,MAAM,CAAC,QAAQ,CACb,cAAc,EACd,gBAAgB,EAChB,KAAK,IAAI,EAAE;QACT,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;QAEvC,OAAO;YACL,QAAQ,EAAE,CAAC;oBACT,GAAG,EAAE,cAAc;oBACnB,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;iBACrC,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,iCAAiC;IACjC,MAAM,CAAC,QAAQ,CACb,uBAAuB,EACvB,gDAAgD,EAChD,KAAK,EAAE,GAAG,EAAE,EAAE;QACZ,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QAE1B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACtC,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAE1C,OAAO;YACL,QAAQ,EAAE,CAAC;oBACT,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE;oBACnB,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;iBACpC,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP resources for project data
|
|
3
|
+
*/
|
|
4
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
import type { JoanApiClient } from '../client/api-client.js';
|
|
6
|
+
export declare function registerProjectResources(server: McpServer, client: JoanApiClient): void;
|
|
7
|
+
//# sourceMappingURL=projects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/resources/projects.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE7D,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAyIvF"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP resources for project data
|
|
3
|
+
*/
|
|
4
|
+
export function registerProjectResources(server, client) {
|
|
5
|
+
// List all projects
|
|
6
|
+
server.resource('joan://projects', 'List all projects', async () => {
|
|
7
|
+
const projects = await client.listProjects({ include_members: true });
|
|
8
|
+
return {
|
|
9
|
+
contents: [{
|
|
10
|
+
uri: 'joan://projects',
|
|
11
|
+
mimeType: 'application/json',
|
|
12
|
+
text: JSON.stringify(projects, null, 2),
|
|
13
|
+
}],
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
// Project details resource template
|
|
17
|
+
server.resource('joan://projects/{projectId}', 'Get detailed information about a specific project', async (uri) => {
|
|
18
|
+
const match = uri.pathname.match(/^\/\/projects\/([^/]+)$/);
|
|
19
|
+
const projectId = match?.[1];
|
|
20
|
+
if (!projectId) {
|
|
21
|
+
throw new Error('Invalid project URI');
|
|
22
|
+
}
|
|
23
|
+
const project = await client.getProject(projectId);
|
|
24
|
+
return {
|
|
25
|
+
contents: [{
|
|
26
|
+
uri: uri.toString(),
|
|
27
|
+
mimeType: 'application/json',
|
|
28
|
+
text: JSON.stringify(project, null, 2),
|
|
29
|
+
}],
|
|
30
|
+
};
|
|
31
|
+
});
|
|
32
|
+
// Project tasks resource template
|
|
33
|
+
server.resource('joan://projects/{projectId}/tasks', 'Get all tasks for a specific project', async (uri) => {
|
|
34
|
+
const match = uri.pathname.match(/^\/\/projects\/([^/]+)\/tasks$/);
|
|
35
|
+
const projectId = match?.[1];
|
|
36
|
+
if (!projectId) {
|
|
37
|
+
throw new Error('Invalid project tasks URI');
|
|
38
|
+
}
|
|
39
|
+
const tasks = await client.getProjectTasks(projectId);
|
|
40
|
+
return {
|
|
41
|
+
contents: [{
|
|
42
|
+
uri: uri.toString(),
|
|
43
|
+
mimeType: 'application/json',
|
|
44
|
+
text: JSON.stringify(tasks, null, 2),
|
|
45
|
+
}],
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
// Project milestones resource template
|
|
49
|
+
server.resource('joan://projects/{projectId}/milestones', 'Get all milestones for a specific project', async (uri) => {
|
|
50
|
+
const match = uri.pathname.match(/^\/\/projects\/([^/]+)\/milestones$/);
|
|
51
|
+
const projectId = match?.[1];
|
|
52
|
+
if (!projectId) {
|
|
53
|
+
throw new Error('Invalid project milestones URI');
|
|
54
|
+
}
|
|
55
|
+
const milestones = await client.listMilestones(projectId, { include_tasks: true });
|
|
56
|
+
return {
|
|
57
|
+
contents: [{
|
|
58
|
+
uri: uri.toString(),
|
|
59
|
+
mimeType: 'application/json',
|
|
60
|
+
text: JSON.stringify(milestones, null, 2),
|
|
61
|
+
}],
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
// Project columns resource template
|
|
65
|
+
server.resource('joan://projects/{projectId}/columns', 'Get kanban columns for a specific project', async (uri) => {
|
|
66
|
+
const match = uri.pathname.match(/^\/\/projects\/([^/]+)\/columns$/);
|
|
67
|
+
const projectId = match?.[1];
|
|
68
|
+
if (!projectId) {
|
|
69
|
+
throw new Error('Invalid project columns URI');
|
|
70
|
+
}
|
|
71
|
+
const columns = await client.getProjectColumns(projectId);
|
|
72
|
+
return {
|
|
73
|
+
contents: [{
|
|
74
|
+
uri: uri.toString(),
|
|
75
|
+
mimeType: 'application/json',
|
|
76
|
+
text: JSON.stringify(columns, null, 2),
|
|
77
|
+
}],
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
// Project analytics resource template
|
|
81
|
+
server.resource('joan://projects/{projectId}/analytics', 'Get analytics and statistics for a specific project', async (uri) => {
|
|
82
|
+
const match = uri.pathname.match(/^\/\/projects\/([^/]+)\/analytics$/);
|
|
83
|
+
const projectId = match?.[1];
|
|
84
|
+
if (!projectId) {
|
|
85
|
+
throw new Error('Invalid project analytics URI');
|
|
86
|
+
}
|
|
87
|
+
const analytics = await client.getProjectAnalytics(projectId);
|
|
88
|
+
return {
|
|
89
|
+
contents: [{
|
|
90
|
+
uri: uri.toString(),
|
|
91
|
+
mimeType: 'application/json',
|
|
92
|
+
text: JSON.stringify(analytics, null, 2),
|
|
93
|
+
}],
|
|
94
|
+
};
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=projects.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/resources/projects.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP resources for task data
|
|
3
|
+
*/
|
|
4
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
import type { JoanApiClient } from '../client/api-client.js';
|
|
6
|
+
export declare function registerTaskResources(server: McpServer, client: JoanApiClient): void;
|
|
7
|
+
//# sourceMappingURL=tasks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.d.ts","sourceRoot":"","sources":["../../src/resources/tasks.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAG7D,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CA2CpF"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP resources for task data
|
|
3
|
+
*/
|
|
4
|
+
import { formatTask } from '../utils/converters.js';
|
|
5
|
+
export function registerTaskResources(server, client) {
|
|
6
|
+
// List all tasks
|
|
7
|
+
server.resource('joan://tasks', 'List all tasks across all projects', async () => {
|
|
8
|
+
const tasks = await client.listTasks();
|
|
9
|
+
const formattedTasks = tasks.map(t => formatTask(t));
|
|
10
|
+
return {
|
|
11
|
+
contents: [{
|
|
12
|
+
uri: 'joan://tasks',
|
|
13
|
+
mimeType: 'application/json',
|
|
14
|
+
text: JSON.stringify(formattedTasks, null, 2),
|
|
15
|
+
}],
|
|
16
|
+
};
|
|
17
|
+
});
|
|
18
|
+
// Task details resource template
|
|
19
|
+
server.resource('joan://tasks/{taskId}', 'Get detailed information about a specific task', async (uri) => {
|
|
20
|
+
const match = uri.pathname.match(/^\/\/tasks\/([^/]+)$/);
|
|
21
|
+
const taskId = match?.[1];
|
|
22
|
+
if (!taskId) {
|
|
23
|
+
throw new Error('Invalid task URI');
|
|
24
|
+
}
|
|
25
|
+
const task = await client.getTaskWithSubtasks(taskId);
|
|
26
|
+
const formattedTask = formatTask(task);
|
|
27
|
+
return {
|
|
28
|
+
contents: [{
|
|
29
|
+
uri: uri.toString(),
|
|
30
|
+
mimeType: 'application/json',
|
|
31
|
+
text: JSON.stringify(formattedTask, null, 2),
|
|
32
|
+
}],
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=tasks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/resources/tasks.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,MAAM,UAAU,qBAAqB,CAAC,MAAiB,EAAE,MAAqB;IAC5E,iBAAiB;IACjB,MAAM,CAAC,QAAQ,CACb,cAAc,EACd,oCAAoC,EACpC,KAAK,IAAI,EAAE;QACT,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;QACvC,MAAM,cAAc,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;QAErD,OAAO;YACL,QAAQ,EAAE,CAAC;oBACT,GAAG,EAAE,cAAc;oBACnB,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC;iBAC9C,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,iCAAiC;IACjC,MAAM,CAAC,QAAQ,CACb,uBAAuB,EACvB,gDAAgD,EAChD,KAAK,EAAE,GAAG,EAAE,EAAE;QACZ,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QAE1B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QACtC,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACtD,MAAM,aAAa,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAEvC,OAAO;YACL,QAAQ,EAAE,CAAC;oBACT,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE;oBACnB,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;iBAC7C,CAAC;SACH,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tools for goal management
|
|
3
|
+
*/
|
|
4
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
+
import type { JoanApiClient } from '../client/api-client.js';
|
|
6
|
+
export declare function registerGoalTools(server: McpServer, client: JoanApiClient): void;
|
|
7
|
+
//# sourceMappingURL=goals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"goals.d.ts","sourceRoot":"","sources":["../../src/tools/goals.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAG7D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAwIhF"}
|