@inkeep/agents-manage-api 0.0.0-dev-20250910232631
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.md +49 -0
- package/README.md +176 -0
- package/dist/__tests__/setup.d.ts +2 -0
- package/dist/__tests__/setup.d.ts.map +1 -0
- package/dist/__tests__/setup.js +26 -0
- package/dist/__tests__/utils/testProject.d.ts +18 -0
- package/dist/__tests__/utils/testProject.d.ts.map +1 -0
- package/dist/__tests__/utils/testProject.js +26 -0
- package/dist/__tests__/utils/testRequest.d.ts +2 -0
- package/dist/__tests__/utils/testRequest.d.ts.map +1 -0
- package/dist/__tests__/utils/testRequest.js +11 -0
- package/dist/__tests__/utils/testTenant.d.ts +64 -0
- package/dist/__tests__/utils/testTenant.d.ts.map +1 -0
- package/dist/__tests__/utils/testTenant.js +71 -0
- package/dist/app.d.ts +5 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +151 -0
- package/dist/data/conversations.d.ts +59 -0
- package/dist/data/conversations.d.ts.map +1 -0
- package/dist/data/conversations.js +216 -0
- package/dist/data/db/clean.d.ts +6 -0
- package/dist/data/db/clean.d.ts.map +1 -0
- package/dist/data/db/clean.js +77 -0
- package/dist/data/db/dbClient.d.ts +3 -0
- package/dist/data/db/dbClient.d.ts.map +1 -0
- package/dist/data/db/dbClient.js +13 -0
- package/dist/data/graphFull.d.ts +11 -0
- package/dist/data/graphFull.d.ts.map +1 -0
- package/dist/data/graphFull.js +90 -0
- package/dist/data/graphFullClient.d.ts +22 -0
- package/dist/data/graphFullClient.d.ts.map +1 -0
- package/dist/data/graphFullClient.js +189 -0
- package/dist/data/tools.d.ts +82 -0
- package/dist/data/tools.d.ts.map +1 -0
- package/dist/data/tools.js +271 -0
- package/dist/env.d.ts +41 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +59 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/logger.d.ts +4 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +32 -0
- package/dist/middleware/auth.d.ts +12 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +36 -0
- package/dist/openapi.d.ts +2 -0
- package/dist/openapi.d.ts.map +1 -0
- package/dist/openapi.js +38 -0
- package/dist/routes/agentArtifactComponents.d.ts +4 -0
- package/dist/routes/agentArtifactComponents.d.ts.map +1 -0
- package/dist/routes/agentArtifactComponents.js +228 -0
- package/dist/routes/agentDataComponents.d.ts +4 -0
- package/dist/routes/agentDataComponents.d.ts.map +1 -0
- package/dist/routes/agentDataComponents.js +224 -0
- package/dist/routes/agentGraph.d.ts +4 -0
- package/dist/routes/agentGraph.d.ts.map +1 -0
- package/dist/routes/agentGraph.js +287 -0
- package/dist/routes/agentRelations.d.ts +4 -0
- package/dist/routes/agentRelations.d.ts.map +1 -0
- package/dist/routes/agentRelations.js +289 -0
- package/dist/routes/agentToolRelations.d.ts +4 -0
- package/dist/routes/agentToolRelations.d.ts.map +1 -0
- package/dist/routes/agentToolRelations.js +342 -0
- package/dist/routes/agents.d.ts +4 -0
- package/dist/routes/agents.d.ts.map +1 -0
- package/dist/routes/agents.js +212 -0
- package/dist/routes/apiKeys.d.ts +4 -0
- package/dist/routes/apiKeys.d.ts.map +1 -0
- package/dist/routes/apiKeys.js +235 -0
- package/dist/routes/artifactComponents.d.ts +4 -0
- package/dist/routes/artifactComponents.d.ts.map +1 -0
- package/dist/routes/artifactComponents.js +201 -0
- package/dist/routes/contextConfigs.d.ts +4 -0
- package/dist/routes/contextConfigs.d.ts.map +1 -0
- package/dist/routes/contextConfigs.js +180 -0
- package/dist/routes/credentials.d.ts +10 -0
- package/dist/routes/credentials.d.ts.map +1 -0
- package/dist/routes/credentials.js +218 -0
- package/dist/routes/dataComponents.d.ts +4 -0
- package/dist/routes/dataComponents.d.ts.map +1 -0
- package/dist/routes/dataComponents.js +187 -0
- package/dist/routes/externalAgents.d.ts +4 -0
- package/dist/routes/externalAgents.d.ts.map +1 -0
- package/dist/routes/externalAgents.js +215 -0
- package/dist/routes/graphFull.d.ts +4 -0
- package/dist/routes/graphFull.d.ts.map +1 -0
- package/dist/routes/graphFull.js +247 -0
- package/dist/routes/index.d.ts +4 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +37 -0
- package/dist/routes/oauth.d.ts +21 -0
- package/dist/routes/oauth.d.ts.map +1 -0
- package/dist/routes/oauth.js +191 -0
- package/dist/routes/projects.d.ts +4 -0
- package/dist/routes/projects.d.ts.map +1 -0
- package/dist/routes/projects.js +220 -0
- package/dist/routes/tools.d.ts +11 -0
- package/dist/routes/tools.d.ts.map +1 -0
- package/dist/routes/tools.js +554 -0
- package/dist/utils/auth-detection.d.ts +22 -0
- package/dist/utils/auth-detection.d.ts.map +1 -0
- package/dist/utils/auth-detection.js +149 -0
- package/dist/utils/oauth-service.d.ts +88 -0
- package/dist/utils/oauth-service.d.ts.map +1 -0
- package/dist/utils/oauth-service.js +240 -0
- package/package.json +69 -0
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
import { createRoute, OpenAPIHono } from '@hono/zod-openapi';
|
|
2
|
+
import { commonGetErrorResponses, createApiError, createTool, dbResultToMcpTool, deleteTool, ErrorResponseSchema, getToolById, IdParamsSchema, ListResponseSchema, listTools, listToolsByStatus, McpToolSchema, PaginationQueryParamsSchema, SingleResponseSchema, TenantProjectParamsSchema, ToolApiInsertSchema, ToolApiUpdateSchema, ToolStatusSchema, updateTool, } from '@inkeep/agents-core';
|
|
3
|
+
import { nanoid } from 'nanoid';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import dbClient from '../data/db/dbClient';
|
|
6
|
+
import { checkAllToolsHealth, checkToolHealth, syncToolDefinitions, updateToolHealth, } from '../data/tools';
|
|
7
|
+
import { getLogger } from '../logger';
|
|
8
|
+
import { oauthService } from '../utils/oauth-service';
|
|
9
|
+
const app = new OpenAPIHono();
|
|
10
|
+
// List tools
|
|
11
|
+
app.openapi(createRoute({
|
|
12
|
+
method: 'get',
|
|
13
|
+
path: '/',
|
|
14
|
+
summary: 'List Tools',
|
|
15
|
+
operationId: 'list-tools',
|
|
16
|
+
tags: ['CRUD Tools'],
|
|
17
|
+
request: {
|
|
18
|
+
params: TenantProjectParamsSchema,
|
|
19
|
+
query: PaginationQueryParamsSchema.extend({
|
|
20
|
+
status: ToolStatusSchema.optional(),
|
|
21
|
+
}),
|
|
22
|
+
},
|
|
23
|
+
responses: {
|
|
24
|
+
200: {
|
|
25
|
+
description: 'List of tools retrieved successfully',
|
|
26
|
+
content: {
|
|
27
|
+
'application/json': {
|
|
28
|
+
schema: ListResponseSchema(McpToolSchema),
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
...commonGetErrorResponses,
|
|
33
|
+
},
|
|
34
|
+
}), async (c) => {
|
|
35
|
+
const { tenantId, projectId } = c.req.valid('param');
|
|
36
|
+
const { page, limit, status } = c.req.valid('query');
|
|
37
|
+
let result;
|
|
38
|
+
// Filter by status if provided
|
|
39
|
+
if (status) {
|
|
40
|
+
const tools = await listToolsByStatus(dbClient)({ scopes: { tenantId, projectId }, status });
|
|
41
|
+
result = {
|
|
42
|
+
data: tools.map((tool) => dbResultToMcpTool(tool)),
|
|
43
|
+
pagination: {
|
|
44
|
+
page: 1,
|
|
45
|
+
limit: tools.length,
|
|
46
|
+
total: tools.length,
|
|
47
|
+
pages: 1,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// Use paginated results from crud operations
|
|
53
|
+
const dbResult = await listTools(dbClient)({
|
|
54
|
+
scopes: { tenantId, projectId },
|
|
55
|
+
pagination: { page, limit },
|
|
56
|
+
});
|
|
57
|
+
result = {
|
|
58
|
+
data: dbResult.data.map((tool) => dbResultToMcpTool(tool)),
|
|
59
|
+
pagination: dbResult.pagination,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return c.json(result);
|
|
63
|
+
});
|
|
64
|
+
// Get tool by ID
|
|
65
|
+
app.openapi(createRoute({
|
|
66
|
+
method: 'get',
|
|
67
|
+
path: '/{id}',
|
|
68
|
+
summary: 'Get Tool',
|
|
69
|
+
operationId: 'get-tool',
|
|
70
|
+
tags: ['CRUD Tools'],
|
|
71
|
+
request: {
|
|
72
|
+
params: TenantProjectParamsSchema.extend(IdParamsSchema.shape),
|
|
73
|
+
},
|
|
74
|
+
responses: {
|
|
75
|
+
200: {
|
|
76
|
+
description: 'Tool found',
|
|
77
|
+
content: {
|
|
78
|
+
'application/json': {
|
|
79
|
+
schema: SingleResponseSchema(McpToolSchema),
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
...commonGetErrorResponses,
|
|
84
|
+
},
|
|
85
|
+
}), async (c) => {
|
|
86
|
+
const { tenantId, projectId, id } = c.req.valid('param');
|
|
87
|
+
const tool = await getToolById(dbClient)({ scopes: { tenantId, projectId }, toolId: id });
|
|
88
|
+
if (!tool) {
|
|
89
|
+
throw createApiError({
|
|
90
|
+
code: 'not_found',
|
|
91
|
+
message: 'Tool not found',
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
return c.json({
|
|
95
|
+
data: dbResultToMcpTool(tool),
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
// Create tool
|
|
99
|
+
app.openapi(createRoute({
|
|
100
|
+
method: 'post',
|
|
101
|
+
path: '/',
|
|
102
|
+
summary: 'Create Tool',
|
|
103
|
+
operationId: 'create-tool',
|
|
104
|
+
tags: ['CRUD Tools'],
|
|
105
|
+
request: {
|
|
106
|
+
params: TenantProjectParamsSchema,
|
|
107
|
+
body: {
|
|
108
|
+
content: {
|
|
109
|
+
'application/json': {
|
|
110
|
+
schema: ToolApiInsertSchema,
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
responses: {
|
|
116
|
+
201: {
|
|
117
|
+
description: 'Tool created successfully',
|
|
118
|
+
content: {
|
|
119
|
+
'application/json': {
|
|
120
|
+
schema: SingleResponseSchema(McpToolSchema),
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
...commonGetErrorResponses,
|
|
125
|
+
},
|
|
126
|
+
}), async (c) => {
|
|
127
|
+
const { tenantId, projectId } = c.req.valid('param');
|
|
128
|
+
const body = c.req.valid('json');
|
|
129
|
+
getLogger().info({ body }, 'body');
|
|
130
|
+
const id = body.id || nanoid();
|
|
131
|
+
const tool = await createTool(dbClient)({
|
|
132
|
+
tenantId,
|
|
133
|
+
projectId,
|
|
134
|
+
id,
|
|
135
|
+
name: body.name,
|
|
136
|
+
config: body.config,
|
|
137
|
+
credentialReferenceId: body.credentialReferenceId,
|
|
138
|
+
imageUrl: body.imageUrl,
|
|
139
|
+
headers: body.headers,
|
|
140
|
+
});
|
|
141
|
+
return c.json({
|
|
142
|
+
data: dbResultToMcpTool(tool),
|
|
143
|
+
}, 201);
|
|
144
|
+
});
|
|
145
|
+
// Update tool
|
|
146
|
+
app.openapi(createRoute({
|
|
147
|
+
method: 'put',
|
|
148
|
+
path: '/{id}',
|
|
149
|
+
summary: 'Update Tool',
|
|
150
|
+
operationId: 'update-tool',
|
|
151
|
+
tags: ['CRUD Tools'],
|
|
152
|
+
request: {
|
|
153
|
+
params: TenantProjectParamsSchema.extend(IdParamsSchema.shape),
|
|
154
|
+
body: {
|
|
155
|
+
content: {
|
|
156
|
+
'application/json': {
|
|
157
|
+
schema: ToolApiUpdateSchema,
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
responses: {
|
|
163
|
+
200: {
|
|
164
|
+
description: 'Tool updated successfully',
|
|
165
|
+
content: {
|
|
166
|
+
'application/json': {
|
|
167
|
+
schema: SingleResponseSchema(McpToolSchema),
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
...commonGetErrorResponses,
|
|
172
|
+
},
|
|
173
|
+
}), async (c) => {
|
|
174
|
+
const { tenantId, projectId, id } = c.req.valid('param');
|
|
175
|
+
const body = c.req.valid('json');
|
|
176
|
+
// Check if there are any fields to update
|
|
177
|
+
if (Object.keys(body).length === 0) {
|
|
178
|
+
throw createApiError({
|
|
179
|
+
code: 'bad_request',
|
|
180
|
+
message: 'No fields to update',
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
const updatedTool = await updateTool(dbClient)({
|
|
184
|
+
scopes: { tenantId, projectId },
|
|
185
|
+
toolId: id,
|
|
186
|
+
data: {
|
|
187
|
+
name: body.name,
|
|
188
|
+
config: body.config,
|
|
189
|
+
credentialReferenceId: body.credentialReferenceId,
|
|
190
|
+
imageUrl: body.imageUrl,
|
|
191
|
+
headers: body.headers,
|
|
192
|
+
},
|
|
193
|
+
});
|
|
194
|
+
if (!updatedTool) {
|
|
195
|
+
throw createApiError({
|
|
196
|
+
code: 'not_found',
|
|
197
|
+
message: 'Tool not found',
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
return c.json({
|
|
201
|
+
data: dbResultToMcpTool(updatedTool),
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
// Delete tool
|
|
205
|
+
app.openapi(createRoute({
|
|
206
|
+
method: 'delete',
|
|
207
|
+
path: '/{id}',
|
|
208
|
+
summary: 'Delete Tool',
|
|
209
|
+
operationId: 'delete-tool',
|
|
210
|
+
tags: ['CRUD Tools'],
|
|
211
|
+
request: {
|
|
212
|
+
params: TenantProjectParamsSchema.extend(IdParamsSchema.shape),
|
|
213
|
+
},
|
|
214
|
+
responses: {
|
|
215
|
+
204: {
|
|
216
|
+
description: 'Tool deleted successfully',
|
|
217
|
+
},
|
|
218
|
+
404: {
|
|
219
|
+
description: 'Tool not found',
|
|
220
|
+
content: {
|
|
221
|
+
'application/json': {
|
|
222
|
+
schema: ErrorResponseSchema,
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
}), async (c) => {
|
|
228
|
+
const { tenantId, projectId, id } = c.req.valid('param');
|
|
229
|
+
const deleted = await deleteTool(dbClient)({ scopes: { tenantId, projectId }, toolId: id });
|
|
230
|
+
if (!deleted) {
|
|
231
|
+
throw createApiError({
|
|
232
|
+
code: 'not_found',
|
|
233
|
+
message: 'Tool not found',
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
return c.body(null, 204);
|
|
237
|
+
});
|
|
238
|
+
// Health check single tool
|
|
239
|
+
app.openapi(createRoute({
|
|
240
|
+
method: 'post',
|
|
241
|
+
path: '/{id}/health-check',
|
|
242
|
+
summary: 'Check Tool Health',
|
|
243
|
+
operationId: 'check-tool-health',
|
|
244
|
+
tags: ['CRUD Tools'],
|
|
245
|
+
request: {
|
|
246
|
+
params: TenantProjectParamsSchema.extend(IdParamsSchema.shape),
|
|
247
|
+
},
|
|
248
|
+
responses: {
|
|
249
|
+
200: {
|
|
250
|
+
description: 'Tool health check completed',
|
|
251
|
+
content: {
|
|
252
|
+
'application/json': {
|
|
253
|
+
schema: SingleResponseSchema(z.object({
|
|
254
|
+
tool: McpToolSchema,
|
|
255
|
+
healthCheck: z.object({
|
|
256
|
+
status: ToolStatusSchema,
|
|
257
|
+
error: z.string().optional(),
|
|
258
|
+
}),
|
|
259
|
+
})),
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
...commonGetErrorResponses,
|
|
264
|
+
},
|
|
265
|
+
}), async (c) => {
|
|
266
|
+
const { tenantId, projectId, id } = c.req.valid('param');
|
|
267
|
+
const tool = await getToolById(dbClient)({ scopes: { tenantId, projectId }, toolId: id });
|
|
268
|
+
if (!tool) {
|
|
269
|
+
throw createApiError({
|
|
270
|
+
code: 'not_found',
|
|
271
|
+
message: 'Tool not found',
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
const credentialStores = c.get('credentialStores');
|
|
275
|
+
const healthResult = await checkToolHealth(dbResultToMcpTool(tool), credentialStores);
|
|
276
|
+
const updatedTool = await updateToolHealth({
|
|
277
|
+
tenantId,
|
|
278
|
+
projectId,
|
|
279
|
+
toolId: id,
|
|
280
|
+
status: healthResult.status,
|
|
281
|
+
error: healthResult.error,
|
|
282
|
+
});
|
|
283
|
+
return c.json({
|
|
284
|
+
data: {
|
|
285
|
+
tool: dbResultToMcpTool(updatedTool),
|
|
286
|
+
healthCheck: healthResult,
|
|
287
|
+
},
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
// Health check all tools for tenant
|
|
291
|
+
app.openapi(createRoute({
|
|
292
|
+
method: 'post',
|
|
293
|
+
path: '/health-check-all',
|
|
294
|
+
summary: 'Check All Tools Health',
|
|
295
|
+
operationId: 'check-all-tools-health',
|
|
296
|
+
tags: ['CRUD Tools'],
|
|
297
|
+
request: {
|
|
298
|
+
params: TenantProjectParamsSchema,
|
|
299
|
+
},
|
|
300
|
+
responses: {
|
|
301
|
+
200: {
|
|
302
|
+
description: 'All tools health check completed',
|
|
303
|
+
content: {
|
|
304
|
+
'application/json': {
|
|
305
|
+
schema: SingleResponseSchema(z.object({
|
|
306
|
+
total: z.number(),
|
|
307
|
+
successful: z.number(),
|
|
308
|
+
failed: z.number(),
|
|
309
|
+
results: z.array(z.object({
|
|
310
|
+
index: z.number(),
|
|
311
|
+
status: z.enum(['fulfilled', 'rejected']),
|
|
312
|
+
data: z.string().optional(),
|
|
313
|
+
error: z.string().optional(),
|
|
314
|
+
})),
|
|
315
|
+
})),
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
},
|
|
319
|
+
...commonGetErrorResponses,
|
|
320
|
+
},
|
|
321
|
+
}), async (c) => {
|
|
322
|
+
const { tenantId, projectId } = c.req.valid('param');
|
|
323
|
+
const credentialStores = c.get('credentialStores');
|
|
324
|
+
const results = await checkAllToolsHealth(tenantId, projectId, credentialStores);
|
|
325
|
+
const summary = {
|
|
326
|
+
total: results.length,
|
|
327
|
+
successful: results.filter((r) => r.status === 'fulfilled').length,
|
|
328
|
+
failed: results.filter((r) => r.status === 'rejected').length,
|
|
329
|
+
results: results.map((result, index) => {
|
|
330
|
+
const baseResult = {
|
|
331
|
+
index,
|
|
332
|
+
status: result.status,
|
|
333
|
+
};
|
|
334
|
+
if (result.status === 'fulfilled') {
|
|
335
|
+
return {
|
|
336
|
+
...baseResult,
|
|
337
|
+
data: `Tool ${index} health check completed`,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
return {
|
|
341
|
+
...baseResult,
|
|
342
|
+
error: result.reason?.message || 'Unknown error',
|
|
343
|
+
};
|
|
344
|
+
}),
|
|
345
|
+
};
|
|
346
|
+
return c.json({ data: summary });
|
|
347
|
+
});
|
|
348
|
+
// Sync tool definitions from MCP server
|
|
349
|
+
app.openapi(createRoute({
|
|
350
|
+
method: 'post',
|
|
351
|
+
path: '/{id}/sync',
|
|
352
|
+
summary: 'Sync Tool Definitions',
|
|
353
|
+
operationId: 'sync-tool-definitions',
|
|
354
|
+
tags: ['CRUD Tools'],
|
|
355
|
+
request: {
|
|
356
|
+
params: TenantProjectParamsSchema.extend(IdParamsSchema.shape),
|
|
357
|
+
},
|
|
358
|
+
responses: {
|
|
359
|
+
200: {
|
|
360
|
+
description: 'Tool definitions synchronized successfully',
|
|
361
|
+
content: {
|
|
362
|
+
'application/json': {
|
|
363
|
+
schema: SingleResponseSchema(McpToolSchema),
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
...commonGetErrorResponses,
|
|
368
|
+
},
|
|
369
|
+
}), async (c) => {
|
|
370
|
+
const { tenantId, projectId, id } = c.req.valid('param');
|
|
371
|
+
// Check if tool exists first
|
|
372
|
+
const tool = await getToolById(dbClient)({ scopes: { tenantId, projectId }, toolId: id });
|
|
373
|
+
if (!tool) {
|
|
374
|
+
throw createApiError({
|
|
375
|
+
code: 'not_found',
|
|
376
|
+
message: 'Tool not found',
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
const credentialStores = c.get('credentialStores');
|
|
380
|
+
const updatedTool = await syncToolDefinitions({
|
|
381
|
+
tenantId,
|
|
382
|
+
projectId,
|
|
383
|
+
toolId: id,
|
|
384
|
+
credentialStoreRegistry: credentialStores,
|
|
385
|
+
});
|
|
386
|
+
return c.json({
|
|
387
|
+
data: dbResultToMcpTool(updatedTool),
|
|
388
|
+
message: 'Tool definitions synchronized successfully',
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
// Get available tools from MCP server (without storing)
|
|
392
|
+
app.openapi(createRoute({
|
|
393
|
+
method: 'get',
|
|
394
|
+
path: '/{id}/available-tools',
|
|
395
|
+
summary: 'Get Available Tools',
|
|
396
|
+
operationId: 'get-available-tools',
|
|
397
|
+
tags: ['CRUD Tools'],
|
|
398
|
+
request: {
|
|
399
|
+
params: TenantProjectParamsSchema.extend(IdParamsSchema.shape),
|
|
400
|
+
},
|
|
401
|
+
responses: {
|
|
402
|
+
200: {
|
|
403
|
+
description: 'Available tools retrieved successfully',
|
|
404
|
+
content: {
|
|
405
|
+
'application/json': {
|
|
406
|
+
schema: SingleResponseSchema(z.object({
|
|
407
|
+
availableTools: z.array(z.object({
|
|
408
|
+
name: z.string(),
|
|
409
|
+
description: z.string().optional(),
|
|
410
|
+
inputSchema: z.record(z.string(), z.unknown()).optional(),
|
|
411
|
+
})),
|
|
412
|
+
lastSync: z.string().optional(),
|
|
413
|
+
status: ToolStatusSchema,
|
|
414
|
+
})),
|
|
415
|
+
},
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
...commonGetErrorResponses,
|
|
419
|
+
},
|
|
420
|
+
}), async (c) => {
|
|
421
|
+
const { tenantId, projectId, id } = c.req.valid('param');
|
|
422
|
+
const tool = await getToolById(dbClient)({ scopes: { tenantId, projectId }, toolId: id });
|
|
423
|
+
if (!tool) {
|
|
424
|
+
throw createApiError({
|
|
425
|
+
code: 'not_found',
|
|
426
|
+
message: 'Tool not found',
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
return c.json({
|
|
430
|
+
data: {
|
|
431
|
+
availableTools: tool.availableTools || [],
|
|
432
|
+
lastSync: tool.lastToolsSync || undefined,
|
|
433
|
+
status: tool.status,
|
|
434
|
+
},
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
// Enable/disable tool
|
|
438
|
+
app.openapi(createRoute({
|
|
439
|
+
method: 'patch',
|
|
440
|
+
path: '/{id}/status',
|
|
441
|
+
summary: 'Update Tool Status',
|
|
442
|
+
operationId: 'update-tool-status',
|
|
443
|
+
tags: ['CRUD Tools'],
|
|
444
|
+
request: {
|
|
445
|
+
params: TenantProjectParamsSchema.extend(IdParamsSchema.shape),
|
|
446
|
+
body: {
|
|
447
|
+
content: {
|
|
448
|
+
'application/json': {
|
|
449
|
+
schema: z.object({
|
|
450
|
+
status: ToolStatusSchema,
|
|
451
|
+
}),
|
|
452
|
+
},
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
},
|
|
456
|
+
responses: {
|
|
457
|
+
200: {
|
|
458
|
+
description: 'Tool status updated successfully',
|
|
459
|
+
content: {
|
|
460
|
+
'application/json': {
|
|
461
|
+
schema: SingleResponseSchema(McpToolSchema),
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
},
|
|
465
|
+
...commonGetErrorResponses,
|
|
466
|
+
},
|
|
467
|
+
}), async (c) => {
|
|
468
|
+
const { tenantId, projectId, id } = c.req.valid('param');
|
|
469
|
+
const { status } = c.req.valid('json');
|
|
470
|
+
const updatedTool = await updateToolHealth({
|
|
471
|
+
tenantId,
|
|
472
|
+
projectId,
|
|
473
|
+
toolId: id,
|
|
474
|
+
status: status,
|
|
475
|
+
});
|
|
476
|
+
return c.json({
|
|
477
|
+
data: dbResultToMcpTool(updatedTool),
|
|
478
|
+
message: `Tool status updated to ${status}`,
|
|
479
|
+
});
|
|
480
|
+
});
|
|
481
|
+
app.openapi(createRoute({
|
|
482
|
+
method: 'get',
|
|
483
|
+
path: '/{id}/oauth-login',
|
|
484
|
+
summary: 'Initiate OAuth login for MCP tool',
|
|
485
|
+
description: 'Detects OAuth requirements and redirects to authorization server',
|
|
486
|
+
operationId: 'initiate-oauth-login',
|
|
487
|
+
tags: ['Tools'],
|
|
488
|
+
request: {
|
|
489
|
+
params: TenantProjectParamsSchema.merge(IdParamsSchema),
|
|
490
|
+
},
|
|
491
|
+
responses: {
|
|
492
|
+
302: {
|
|
493
|
+
description: 'Redirect to OAuth authorization server',
|
|
494
|
+
},
|
|
495
|
+
400: {
|
|
496
|
+
description: 'OAuth not supported or configuration error',
|
|
497
|
+
content: {
|
|
498
|
+
'application/json': {
|
|
499
|
+
schema: ErrorResponseSchema,
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
},
|
|
503
|
+
404: {
|
|
504
|
+
description: 'Tool not found',
|
|
505
|
+
content: {
|
|
506
|
+
'application/json': {
|
|
507
|
+
schema: ErrorResponseSchema,
|
|
508
|
+
},
|
|
509
|
+
},
|
|
510
|
+
},
|
|
511
|
+
500: {
|
|
512
|
+
description: 'Internal server error',
|
|
513
|
+
content: {
|
|
514
|
+
'application/json': {
|
|
515
|
+
schema: ErrorResponseSchema,
|
|
516
|
+
},
|
|
517
|
+
},
|
|
518
|
+
},
|
|
519
|
+
},
|
|
520
|
+
}), async (c) => {
|
|
521
|
+
const { tenantId, projectId, id } = c.req.valid('param');
|
|
522
|
+
const logger = getLogger('oauth-login');
|
|
523
|
+
try {
|
|
524
|
+
// 1. Get the tool
|
|
525
|
+
const tool = await getToolById(dbClient)({ scopes: { tenantId, projectId }, toolId: id });
|
|
526
|
+
if (!tool) {
|
|
527
|
+
throw createApiError({
|
|
528
|
+
code: 'not_found',
|
|
529
|
+
message: 'Tool not found',
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
const mcpTool = dbResultToMcpTool(tool);
|
|
533
|
+
// 2. Initiate OAuth flow using centralized service
|
|
534
|
+
const { redirectUrl } = await oauthService.initiateOAuthFlow({
|
|
535
|
+
tool: mcpTool,
|
|
536
|
+
tenantId,
|
|
537
|
+
projectId,
|
|
538
|
+
toolId: id,
|
|
539
|
+
});
|
|
540
|
+
// 4. Immediate redirect
|
|
541
|
+
return c.redirect(redirectUrl, 302);
|
|
542
|
+
}
|
|
543
|
+
catch (error) {
|
|
544
|
+
logger.error({ toolId: id, error }, 'OAuth login failed');
|
|
545
|
+
if (error && typeof error === 'object' && 'code' in error) {
|
|
546
|
+
const apiError = error;
|
|
547
|
+
return c.json({ error: apiError.message }, apiError.code === 'not_found' ? 404 : 400);
|
|
548
|
+
}
|
|
549
|
+
return c.json({
|
|
550
|
+
error: 'Failed to initiate OAuth login',
|
|
551
|
+
}, 500);
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
export default app;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized authentication detection utilities for MCP tools
|
|
3
|
+
*/
|
|
4
|
+
import type { McpTool } from '@inkeep/agents-core';
|
|
5
|
+
/**
|
|
6
|
+
* OAuth configuration interface
|
|
7
|
+
*/
|
|
8
|
+
export interface OAuthConfig {
|
|
9
|
+
authorizationUrl: string;
|
|
10
|
+
tokenUrl: string;
|
|
11
|
+
registrationUrl?: string;
|
|
12
|
+
supportsDynamicRegistration: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Full OAuth endpoint discovery with complete configuration
|
|
16
|
+
*/
|
|
17
|
+
export declare const discoverOAuthEndpoints: (serverUrl: string) => Promise<OAuthConfig | null>;
|
|
18
|
+
/**
|
|
19
|
+
* Detect if OAuth 2.1/PKCE authentication is specifically required for a tool
|
|
20
|
+
*/
|
|
21
|
+
export declare const detectAuthenticationRequired: (tool: McpTool, error: Error) => Promise<boolean>;
|
|
22
|
+
//# sourceMappingURL=auth-detection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-detection.d.ts","sourceRoot":"","sources":["../../src/utils/auth-detection.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAKnD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2BAA2B,EAAE,OAAO,CAAC;CACtC;AA0DD;;GAEG;AACH,eAAO,MAAM,sBAAsB,GAAU,WAAW,MAAM,KAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAkC1F,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,4BAA4B,GACvC,MAAM,OAAO,EACb,OAAO,KAAK,KACX,OAAO,CAAC,OAAO,CAsEjB,CAAC"}
|