@cerema/cadriciel-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Dockerfile +26 -0
- package/README.md +98 -0
- package/dist/client.d.ts +31 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +77 -0
- package/dist/client.js.map +1 -0
- package/dist/http-server.d.ts +13 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +184 -0
- package/dist/http-server.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +64 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/database.d.ts +70 -0
- package/dist/tools/database.d.ts.map +1 -0
- package/dist/tools/database.js +77 -0
- package/dist/tools/database.js.map +1 -0
- package/dist/tools/deploy.d.ts +73 -0
- package/dist/tools/deploy.d.ts.map +1 -0
- package/dist/tools/deploy.js +103 -0
- package/dist/tools/deploy.js.map +1 -0
- package/dist/tools/handlers.d.ts +13 -0
- package/dist/tools/handlers.d.ts.map +1 -0
- package/dist/tools/handlers.js +225 -0
- package/dist/tools/handlers.js.map +1 -0
- package/dist/tools/index.d.ts +11 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +298 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/projects.d.ts +45 -0
- package/dist/tools/projects.d.ts.map +1 -0
- package/dist/tools/projects.js +71 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/workflows.d.ts +66 -0
- package/dist/tools/workflows.d.ts.map +1 -0
- package/dist/tools/workflows.js +90 -0
- package/dist/tools/workflows.js.map +1 -0
- package/k8s/deployment.yaml +48 -0
- package/k8s/ingress.yaml +27 -0
- package/k8s/kustomization.yaml +14 -0
- package/k8s/service.yaml +15 -0
- package/package.json +36 -0
- package/src/client.ts +97 -0
- package/src/http-server.ts +213 -0
- package/src/index.ts +75 -0
- package/src/tools/database.ts +105 -0
- package/src/tools/deploy.ts +127 -0
- package/src/tools/handlers.ts +241 -0
- package/src/tools/index.ts +275 -0
- package/src/tools/projects.ts +89 -0
- package/src/tools/workflows.ts +117 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Handlers Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates tool handlers bound to a specific Cadriciel client.
|
|
5
|
+
* Used by the HTTP server where each session has its own client.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
9
|
+
import {
|
|
10
|
+
CallToolRequestSchema,
|
|
11
|
+
ListToolsRequestSchema,
|
|
12
|
+
} from '@modelcontextprotocol/sdk/types.js';
|
|
13
|
+
import { CadricielClient } from '../client';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Tool definitions (schema only, handlers are created dynamically)
|
|
17
|
+
*/
|
|
18
|
+
const TOOL_DEFINITIONS = [
|
|
19
|
+
{
|
|
20
|
+
name: 'list_projects',
|
|
21
|
+
description: 'List all Cadriciel projects accessible by the authenticated user',
|
|
22
|
+
inputSchema: {
|
|
23
|
+
type: 'object' as const,
|
|
24
|
+
properties: {},
|
|
25
|
+
required: [],
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'get_project',
|
|
30
|
+
description: 'Get detailed information about a specific project',
|
|
31
|
+
inputSchema: {
|
|
32
|
+
type: 'object' as const,
|
|
33
|
+
properties: {
|
|
34
|
+
projectId: {
|
|
35
|
+
type: 'number',
|
|
36
|
+
description: 'The project ID',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
required: ['projectId'],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'list_workflows',
|
|
44
|
+
description: 'List all workflows in a workspace',
|
|
45
|
+
inputSchema: {
|
|
46
|
+
type: 'object' as const,
|
|
47
|
+
properties: {
|
|
48
|
+
workspaceId: {
|
|
49
|
+
type: 'number',
|
|
50
|
+
description: 'The workspace/project ID',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
required: ['workspaceId'],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'execute_workflow',
|
|
58
|
+
description: 'Execute a workflow with optional input parameters',
|
|
59
|
+
inputSchema: {
|
|
60
|
+
type: 'object' as const,
|
|
61
|
+
properties: {
|
|
62
|
+
workspaceId: {
|
|
63
|
+
type: 'number',
|
|
64
|
+
description: 'The workspace/project ID',
|
|
65
|
+
},
|
|
66
|
+
workflowId: {
|
|
67
|
+
type: 'string',
|
|
68
|
+
description: 'The workflow ID to execute',
|
|
69
|
+
},
|
|
70
|
+
input: {
|
|
71
|
+
type: 'object',
|
|
72
|
+
description: 'Input parameters for the workflow',
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
required: ['workspaceId', 'workflowId'],
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'get_execution',
|
|
80
|
+
description: 'Get the status and results of a workflow execution',
|
|
81
|
+
inputSchema: {
|
|
82
|
+
type: 'object' as const,
|
|
83
|
+
properties: {
|
|
84
|
+
workspaceId: {
|
|
85
|
+
type: 'number',
|
|
86
|
+
description: 'The workspace/project ID',
|
|
87
|
+
},
|
|
88
|
+
executionId: {
|
|
89
|
+
type: 'string',
|
|
90
|
+
description: 'The execution ID',
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
required: ['workspaceId', 'executionId'],
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'get_schema',
|
|
98
|
+
description: 'Get the database schema (tables, columns, relationships)',
|
|
99
|
+
inputSchema: {
|
|
100
|
+
type: 'object' as const,
|
|
101
|
+
properties: {
|
|
102
|
+
workspaceId: {
|
|
103
|
+
type: 'number',
|
|
104
|
+
description: 'The workspace/project ID',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
required: ['workspaceId'],
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: 'query_database',
|
|
112
|
+
description: 'Execute a read-only SQL query (SELECT only)',
|
|
113
|
+
inputSchema: {
|
|
114
|
+
type: 'object' as const,
|
|
115
|
+
properties: {
|
|
116
|
+
workspaceId: {
|
|
117
|
+
type: 'number',
|
|
118
|
+
description: 'The workspace/project ID',
|
|
119
|
+
},
|
|
120
|
+
query: {
|
|
121
|
+
type: 'string',
|
|
122
|
+
description: 'SQL SELECT query to execute',
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
required: ['workspaceId', 'query'],
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
];
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Create tool handler implementations bound to a client
|
|
132
|
+
*/
|
|
133
|
+
function createHandlers(client: CadricielClient) {
|
|
134
|
+
return {
|
|
135
|
+
// ============================================================
|
|
136
|
+
// IMPLEMENTED
|
|
137
|
+
// ============================================================
|
|
138
|
+
|
|
139
|
+
async list_projects() {
|
|
140
|
+
const response = await client.get('/api/studio/projects');
|
|
141
|
+
if (!response.success) {
|
|
142
|
+
throw new Error(`Failed to list projects: ${response.error}`);
|
|
143
|
+
}
|
|
144
|
+
const projects = (response.data || []).map((p: any) => ({
|
|
145
|
+
id: p.id,
|
|
146
|
+
name: p.name || p.title,
|
|
147
|
+
description: p.description,
|
|
148
|
+
path: p.path || p.path_with_namespace,
|
|
149
|
+
created_at: p.created_at,
|
|
150
|
+
updated_at: p.updated_at || p.last_activity_at,
|
|
151
|
+
}));
|
|
152
|
+
return { projects };
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
// ============================================================
|
|
156
|
+
// TODO: Implement these
|
|
157
|
+
// ============================================================
|
|
158
|
+
|
|
159
|
+
async get_project(args: { projectId: number }) {
|
|
160
|
+
// TODO: Implement
|
|
161
|
+
// const response = await client.get(`/api/studio/workspace/${args.projectId}`);
|
|
162
|
+
throw new Error('Not implemented yet');
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
async list_workflows(args: { workspaceId: number }) {
|
|
166
|
+
// TODO: Implement
|
|
167
|
+
// const response = await client.get(`/api/studio/workspace/${args.workspaceId}/airjobs/workflows`);
|
|
168
|
+
throw new Error('Not implemented yet');
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
async execute_workflow(args: { workspaceId: number; workflowId: string; input?: any }) {
|
|
172
|
+
// TODO: Implement
|
|
173
|
+
// const response = await client.post(`/api/studio/workspace/${args.workspaceId}/airjobs/execute`, { ... });
|
|
174
|
+
throw new Error('Not implemented yet');
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
async get_execution(args: { workspaceId: number; executionId: string }) {
|
|
178
|
+
// TODO: Implement
|
|
179
|
+
// const response = await client.get(`/api/studio/workspace/${args.workspaceId}/airjobs/executions?id=${args.executionId}`);
|
|
180
|
+
throw new Error('Not implemented yet');
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
async get_schema(args: { workspaceId: number }) {
|
|
184
|
+
// TODO: Implement
|
|
185
|
+
// const response = await client.get(`/api/studio/workspace/${args.workspaceId}/db/tables`);
|
|
186
|
+
throw new Error('Not implemented yet');
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
async query_database(args: { workspaceId: number; query: string }) {
|
|
190
|
+
// TODO: Implement
|
|
191
|
+
// IMPORTANT: Validate query is SELECT only
|
|
192
|
+
// const response = await client.post(`/api/studio/workspace/${args.workspaceId}/db/sql`, { sql: args.query });
|
|
193
|
+
throw new Error('Not implemented yet');
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Register tool handlers with an MCP server
|
|
200
|
+
*/
|
|
201
|
+
export function createToolHandlers(server: Server, client: CadricielClient): void {
|
|
202
|
+
const handlers = createHandlers(client);
|
|
203
|
+
|
|
204
|
+
// List available tools
|
|
205
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
206
|
+
return { tools: TOOL_DEFINITIONS };
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Handle tool calls
|
|
210
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
211
|
+
const { name, arguments: args } = request.params;
|
|
212
|
+
|
|
213
|
+
const handler = (handlers as any)[name];
|
|
214
|
+
if (!handler) {
|
|
215
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
try {
|
|
219
|
+
const result = await handler(args);
|
|
220
|
+
return {
|
|
221
|
+
content: [
|
|
222
|
+
{
|
|
223
|
+
type: 'text',
|
|
224
|
+
text: JSON.stringify(result, null, 2),
|
|
225
|
+
},
|
|
226
|
+
],
|
|
227
|
+
};
|
|
228
|
+
} catch (error) {
|
|
229
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
230
|
+
return {
|
|
231
|
+
content: [
|
|
232
|
+
{
|
|
233
|
+
type: 'text',
|
|
234
|
+
text: `Error: ${message}`,
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
isError: true,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Registry
|
|
3
|
+
*
|
|
4
|
+
* Registers all available MCP tools with their schemas and handlers.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
8
|
+
import {
|
|
9
|
+
CallToolRequestSchema,
|
|
10
|
+
ListToolsRequestSchema,
|
|
11
|
+
} from '@modelcontextprotocol/sdk/types.js';
|
|
12
|
+
|
|
13
|
+
import * as projects from './projects';
|
|
14
|
+
import * as workflows from './workflows';
|
|
15
|
+
import * as database from './database';
|
|
16
|
+
import * as deploy from './deploy';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Tool definitions for MCP
|
|
20
|
+
*/
|
|
21
|
+
const TOOLS = [
|
|
22
|
+
// ============================================================
|
|
23
|
+
// IMPLEMENTED
|
|
24
|
+
// ============================================================
|
|
25
|
+
{
|
|
26
|
+
name: 'list_projects',
|
|
27
|
+
description: 'List all Cadriciel projects accessible by the authenticated user',
|
|
28
|
+
inputSchema: {
|
|
29
|
+
type: 'object',
|
|
30
|
+
properties: {},
|
|
31
|
+
required: [],
|
|
32
|
+
},
|
|
33
|
+
handler: projects.listProjects,
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
// ============================================================
|
|
37
|
+
// TODO: Implement handlers for these tools
|
|
38
|
+
// ============================================================
|
|
39
|
+
{
|
|
40
|
+
name: 'get_project',
|
|
41
|
+
description: 'Get detailed information about a specific project',
|
|
42
|
+
inputSchema: {
|
|
43
|
+
type: 'object',
|
|
44
|
+
properties: {
|
|
45
|
+
projectId: {
|
|
46
|
+
type: 'number',
|
|
47
|
+
description: 'The project ID',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
required: ['projectId'],
|
|
51
|
+
},
|
|
52
|
+
handler: async (args: { projectId: number }) => {
|
|
53
|
+
// TODO: Implement
|
|
54
|
+
throw new Error('Not implemented yet - see tools/projects.ts');
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'list_workflows',
|
|
59
|
+
description: 'List all workflows in a workspace',
|
|
60
|
+
inputSchema: {
|
|
61
|
+
type: 'object',
|
|
62
|
+
properties: {
|
|
63
|
+
workspaceId: {
|
|
64
|
+
type: 'number',
|
|
65
|
+
description: 'The workspace/project ID',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
required: ['workspaceId'],
|
|
69
|
+
},
|
|
70
|
+
handler: async (args: { workspaceId: number }) => {
|
|
71
|
+
// TODO: Implement
|
|
72
|
+
throw new Error('Not implemented yet - see tools/workflows.ts');
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'execute_workflow',
|
|
77
|
+
description: 'Execute a workflow with optional input parameters',
|
|
78
|
+
inputSchema: {
|
|
79
|
+
type: 'object',
|
|
80
|
+
properties: {
|
|
81
|
+
workspaceId: {
|
|
82
|
+
type: 'number',
|
|
83
|
+
description: 'The workspace/project ID',
|
|
84
|
+
},
|
|
85
|
+
workflowId: {
|
|
86
|
+
type: 'string',
|
|
87
|
+
description: 'The workflow ID to execute',
|
|
88
|
+
},
|
|
89
|
+
input: {
|
|
90
|
+
type: 'object',
|
|
91
|
+
description: 'Input parameters for the workflow',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
required: ['workspaceId', 'workflowId'],
|
|
95
|
+
},
|
|
96
|
+
handler: async (args: { workspaceId: number; workflowId: string; input?: any }) => {
|
|
97
|
+
// TODO: Implement
|
|
98
|
+
throw new Error('Not implemented yet - see tools/workflows.ts');
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: 'get_execution',
|
|
103
|
+
description: 'Get the status and results of a workflow execution',
|
|
104
|
+
inputSchema: {
|
|
105
|
+
type: 'object',
|
|
106
|
+
properties: {
|
|
107
|
+
workspaceId: {
|
|
108
|
+
type: 'number',
|
|
109
|
+
description: 'The workspace/project ID',
|
|
110
|
+
},
|
|
111
|
+
executionId: {
|
|
112
|
+
type: 'string',
|
|
113
|
+
description: 'The execution ID',
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
required: ['workspaceId', 'executionId'],
|
|
117
|
+
},
|
|
118
|
+
handler: async (args: { workspaceId: number; executionId: string }) => {
|
|
119
|
+
// TODO: Implement
|
|
120
|
+
throw new Error('Not implemented yet - see tools/workflows.ts');
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
name: 'get_schema',
|
|
125
|
+
description: 'Get the database schema (tables, columns, relationships)',
|
|
126
|
+
inputSchema: {
|
|
127
|
+
type: 'object',
|
|
128
|
+
properties: {
|
|
129
|
+
workspaceId: {
|
|
130
|
+
type: 'number',
|
|
131
|
+
description: 'The workspace/project ID',
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
required: ['workspaceId'],
|
|
135
|
+
},
|
|
136
|
+
handler: async (args: { workspaceId: number }) => {
|
|
137
|
+
// TODO: Implement
|
|
138
|
+
throw new Error('Not implemented yet - see tools/database.ts');
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: 'query_database',
|
|
143
|
+
description: 'Execute a read-only SQL query (SELECT only)',
|
|
144
|
+
inputSchema: {
|
|
145
|
+
type: 'object',
|
|
146
|
+
properties: {
|
|
147
|
+
workspaceId: {
|
|
148
|
+
type: 'number',
|
|
149
|
+
description: 'The workspace/project ID',
|
|
150
|
+
},
|
|
151
|
+
query: {
|
|
152
|
+
type: 'string',
|
|
153
|
+
description: 'SQL SELECT query to execute',
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
required: ['workspaceId', 'query'],
|
|
157
|
+
},
|
|
158
|
+
handler: async (args: { workspaceId: number; query: string }) => {
|
|
159
|
+
// TODO: Implement
|
|
160
|
+
throw new Error('Not implemented yet - see tools/database.ts');
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
name: 'get_deployment_status',
|
|
165
|
+
description: 'Get the current deployment status of a project',
|
|
166
|
+
inputSchema: {
|
|
167
|
+
type: 'object',
|
|
168
|
+
properties: {
|
|
169
|
+
workspaceId: {
|
|
170
|
+
type: 'number',
|
|
171
|
+
description: 'The workspace/project ID',
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
required: ['workspaceId'],
|
|
175
|
+
},
|
|
176
|
+
handler: async (args: { workspaceId: number }) => {
|
|
177
|
+
// TODO: Implement
|
|
178
|
+
throw new Error('Not implemented yet - see tools/deploy.ts');
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
name: 'get_env_vars',
|
|
183
|
+
description: 'Get environment variables for a project (values hidden)',
|
|
184
|
+
inputSchema: {
|
|
185
|
+
type: 'object',
|
|
186
|
+
properties: {
|
|
187
|
+
workspaceId: {
|
|
188
|
+
type: 'number',
|
|
189
|
+
description: 'The workspace/project ID',
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
required: ['workspaceId'],
|
|
193
|
+
},
|
|
194
|
+
handler: async (args: { workspaceId: number }) => {
|
|
195
|
+
// TODO: Implement
|
|
196
|
+
throw new Error('Not implemented yet - see tools/deploy.ts');
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
name: 'service_control',
|
|
201
|
+
description: 'Control services (start, stop, restart)',
|
|
202
|
+
inputSchema: {
|
|
203
|
+
type: 'object',
|
|
204
|
+
properties: {
|
|
205
|
+
workspaceId: {
|
|
206
|
+
type: 'number',
|
|
207
|
+
description: 'The workspace/project ID',
|
|
208
|
+
},
|
|
209
|
+
action: {
|
|
210
|
+
type: 'string',
|
|
211
|
+
enum: ['start', 'stop', 'restart'],
|
|
212
|
+
description: 'Action to perform',
|
|
213
|
+
},
|
|
214
|
+
service: {
|
|
215
|
+
type: 'string',
|
|
216
|
+
description: 'Optional specific service name',
|
|
217
|
+
},
|
|
218
|
+
},
|
|
219
|
+
required: ['workspaceId', 'action'],
|
|
220
|
+
},
|
|
221
|
+
handler: async (args: { workspaceId: number; action: string; service?: string }) => {
|
|
222
|
+
// TODO: Implement
|
|
223
|
+
throw new Error('Not implemented yet - see tools/deploy.ts');
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
];
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Register all tools with the MCP server
|
|
230
|
+
*/
|
|
231
|
+
export function registerTools(server: Server): void {
|
|
232
|
+
// List available tools
|
|
233
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
234
|
+
return {
|
|
235
|
+
tools: TOOLS.map(({ name, description, inputSchema }) => ({
|
|
236
|
+
name,
|
|
237
|
+
description,
|
|
238
|
+
inputSchema,
|
|
239
|
+
})),
|
|
240
|
+
};
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// Handle tool calls
|
|
244
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
245
|
+
const { name, arguments: args } = request.params;
|
|
246
|
+
|
|
247
|
+
const tool = TOOLS.find((t) => t.name === name);
|
|
248
|
+
if (!tool) {
|
|
249
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
try {
|
|
253
|
+
const result = await tool.handler(args as any);
|
|
254
|
+
return {
|
|
255
|
+
content: [
|
|
256
|
+
{
|
|
257
|
+
type: 'text',
|
|
258
|
+
text: JSON.stringify(result, null, 2),
|
|
259
|
+
},
|
|
260
|
+
],
|
|
261
|
+
};
|
|
262
|
+
} catch (error) {
|
|
263
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
264
|
+
return {
|
|
265
|
+
content: [
|
|
266
|
+
{
|
|
267
|
+
type: 'text',
|
|
268
|
+
text: `Error: ${message}`,
|
|
269
|
+
},
|
|
270
|
+
],
|
|
271
|
+
isError: true,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project Tools
|
|
3
|
+
*
|
|
4
|
+
* Tools for managing Cadriciel projects.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { getClient } from '../client';
|
|
8
|
+
|
|
9
|
+
// ============================================================
|
|
10
|
+
// IMPLEMENTED
|
|
11
|
+
// ============================================================
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* List all projects accessible by the authenticated user
|
|
15
|
+
*/
|
|
16
|
+
export async function listProjects(): Promise<{
|
|
17
|
+
projects: Array<{
|
|
18
|
+
id: number;
|
|
19
|
+
name: string;
|
|
20
|
+
description?: string;
|
|
21
|
+
path: string;
|
|
22
|
+
created_at: string;
|
|
23
|
+
updated_at: string;
|
|
24
|
+
}>;
|
|
25
|
+
}> {
|
|
26
|
+
const client = getClient();
|
|
27
|
+
const response = await client.get('/api/studio/projects');
|
|
28
|
+
|
|
29
|
+
if (!response.success) {
|
|
30
|
+
throw new Error(`Failed to list projects: ${response.error}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Map the response to a cleaner format
|
|
34
|
+
const projects = (response.data || []).map((p: any) => ({
|
|
35
|
+
id: p.id,
|
|
36
|
+
name: p.name || p.title,
|
|
37
|
+
description: p.description,
|
|
38
|
+
path: p.path || p.path_with_namespace,
|
|
39
|
+
created_at: p.created_at,
|
|
40
|
+
updated_at: p.updated_at || p.last_activity_at,
|
|
41
|
+
}));
|
|
42
|
+
|
|
43
|
+
return { projects };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ============================================================
|
|
47
|
+
// TODO: Implement these tools
|
|
48
|
+
// ============================================================
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* TODO: Get detailed information about a specific project
|
|
52
|
+
*
|
|
53
|
+
* @param projectId - The project ID
|
|
54
|
+
* @returns Project details including config, members, environments
|
|
55
|
+
*/
|
|
56
|
+
export async function getProject(projectId: number): Promise<any> {
|
|
57
|
+
// TODO: Implement
|
|
58
|
+
// Endpoint: GET /api/studio/workspace/:projectId
|
|
59
|
+
throw new Error('Not implemented yet');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* TODO: Create a new project
|
|
64
|
+
*
|
|
65
|
+
* @param options - Project creation options
|
|
66
|
+
* @returns Created project details
|
|
67
|
+
*/
|
|
68
|
+
export async function createProject(options: {
|
|
69
|
+
title: string;
|
|
70
|
+
description?: string;
|
|
71
|
+
template?: string;
|
|
72
|
+
mode?: 'fullstack' | 'frontend' | 'backend';
|
|
73
|
+
backendType?: 'node' | 'python' | 'springboot';
|
|
74
|
+
}): Promise<any> {
|
|
75
|
+
// TODO: Implement
|
|
76
|
+
// Endpoint: POST /api/studio/projects
|
|
77
|
+
throw new Error('Not implemented yet');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* TODO: Delete a project
|
|
82
|
+
*
|
|
83
|
+
* @param projectId - The project ID to delete
|
|
84
|
+
*/
|
|
85
|
+
export async function deleteProject(projectId: number): Promise<void> {
|
|
86
|
+
// TODO: Implement
|
|
87
|
+
// Endpoint: DELETE /api/studio/projects/:projectId
|
|
88
|
+
throw new Error('Not implemented yet');
|
|
89
|
+
}
|