@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.
Files changed (108) hide show
  1. package/LICENSE.md +49 -0
  2. package/README.md +176 -0
  3. package/dist/__tests__/setup.d.ts +2 -0
  4. package/dist/__tests__/setup.d.ts.map +1 -0
  5. package/dist/__tests__/setup.js +26 -0
  6. package/dist/__tests__/utils/testProject.d.ts +18 -0
  7. package/dist/__tests__/utils/testProject.d.ts.map +1 -0
  8. package/dist/__tests__/utils/testProject.js +26 -0
  9. package/dist/__tests__/utils/testRequest.d.ts +2 -0
  10. package/dist/__tests__/utils/testRequest.d.ts.map +1 -0
  11. package/dist/__tests__/utils/testRequest.js +11 -0
  12. package/dist/__tests__/utils/testTenant.d.ts +64 -0
  13. package/dist/__tests__/utils/testTenant.d.ts.map +1 -0
  14. package/dist/__tests__/utils/testTenant.js +71 -0
  15. package/dist/app.d.ts +5 -0
  16. package/dist/app.d.ts.map +1 -0
  17. package/dist/app.js +151 -0
  18. package/dist/data/conversations.d.ts +59 -0
  19. package/dist/data/conversations.d.ts.map +1 -0
  20. package/dist/data/conversations.js +216 -0
  21. package/dist/data/db/clean.d.ts +6 -0
  22. package/dist/data/db/clean.d.ts.map +1 -0
  23. package/dist/data/db/clean.js +77 -0
  24. package/dist/data/db/dbClient.d.ts +3 -0
  25. package/dist/data/db/dbClient.d.ts.map +1 -0
  26. package/dist/data/db/dbClient.js +13 -0
  27. package/dist/data/graphFull.d.ts +11 -0
  28. package/dist/data/graphFull.d.ts.map +1 -0
  29. package/dist/data/graphFull.js +90 -0
  30. package/dist/data/graphFullClient.d.ts +22 -0
  31. package/dist/data/graphFullClient.d.ts.map +1 -0
  32. package/dist/data/graphFullClient.js +189 -0
  33. package/dist/data/tools.d.ts +82 -0
  34. package/dist/data/tools.d.ts.map +1 -0
  35. package/dist/data/tools.js +271 -0
  36. package/dist/env.d.ts +41 -0
  37. package/dist/env.d.ts.map +1 -0
  38. package/dist/env.js +59 -0
  39. package/dist/index.d.ts +10 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +27 -0
  42. package/dist/logger.d.ts +4 -0
  43. package/dist/logger.d.ts.map +1 -0
  44. package/dist/logger.js +32 -0
  45. package/dist/middleware/auth.d.ts +12 -0
  46. package/dist/middleware/auth.d.ts.map +1 -0
  47. package/dist/middleware/auth.js +36 -0
  48. package/dist/openapi.d.ts +2 -0
  49. package/dist/openapi.d.ts.map +1 -0
  50. package/dist/openapi.js +38 -0
  51. package/dist/routes/agentArtifactComponents.d.ts +4 -0
  52. package/dist/routes/agentArtifactComponents.d.ts.map +1 -0
  53. package/dist/routes/agentArtifactComponents.js +228 -0
  54. package/dist/routes/agentDataComponents.d.ts +4 -0
  55. package/dist/routes/agentDataComponents.d.ts.map +1 -0
  56. package/dist/routes/agentDataComponents.js +224 -0
  57. package/dist/routes/agentGraph.d.ts +4 -0
  58. package/dist/routes/agentGraph.d.ts.map +1 -0
  59. package/dist/routes/agentGraph.js +287 -0
  60. package/dist/routes/agentRelations.d.ts +4 -0
  61. package/dist/routes/agentRelations.d.ts.map +1 -0
  62. package/dist/routes/agentRelations.js +289 -0
  63. package/dist/routes/agentToolRelations.d.ts +4 -0
  64. package/dist/routes/agentToolRelations.d.ts.map +1 -0
  65. package/dist/routes/agentToolRelations.js +342 -0
  66. package/dist/routes/agents.d.ts +4 -0
  67. package/dist/routes/agents.d.ts.map +1 -0
  68. package/dist/routes/agents.js +212 -0
  69. package/dist/routes/apiKeys.d.ts +4 -0
  70. package/dist/routes/apiKeys.d.ts.map +1 -0
  71. package/dist/routes/apiKeys.js +235 -0
  72. package/dist/routes/artifactComponents.d.ts +4 -0
  73. package/dist/routes/artifactComponents.d.ts.map +1 -0
  74. package/dist/routes/artifactComponents.js +201 -0
  75. package/dist/routes/contextConfigs.d.ts +4 -0
  76. package/dist/routes/contextConfigs.d.ts.map +1 -0
  77. package/dist/routes/contextConfigs.js +180 -0
  78. package/dist/routes/credentials.d.ts +10 -0
  79. package/dist/routes/credentials.d.ts.map +1 -0
  80. package/dist/routes/credentials.js +218 -0
  81. package/dist/routes/dataComponents.d.ts +4 -0
  82. package/dist/routes/dataComponents.d.ts.map +1 -0
  83. package/dist/routes/dataComponents.js +187 -0
  84. package/dist/routes/externalAgents.d.ts +4 -0
  85. package/dist/routes/externalAgents.d.ts.map +1 -0
  86. package/dist/routes/externalAgents.js +215 -0
  87. package/dist/routes/graphFull.d.ts +4 -0
  88. package/dist/routes/graphFull.d.ts.map +1 -0
  89. package/dist/routes/graphFull.js +247 -0
  90. package/dist/routes/index.d.ts +4 -0
  91. package/dist/routes/index.d.ts.map +1 -0
  92. package/dist/routes/index.js +37 -0
  93. package/dist/routes/oauth.d.ts +21 -0
  94. package/dist/routes/oauth.d.ts.map +1 -0
  95. package/dist/routes/oauth.js +191 -0
  96. package/dist/routes/projects.d.ts +4 -0
  97. package/dist/routes/projects.d.ts.map +1 -0
  98. package/dist/routes/projects.js +220 -0
  99. package/dist/routes/tools.d.ts +11 -0
  100. package/dist/routes/tools.d.ts.map +1 -0
  101. package/dist/routes/tools.js +554 -0
  102. package/dist/utils/auth-detection.d.ts +22 -0
  103. package/dist/utils/auth-detection.d.ts.map +1 -0
  104. package/dist/utils/auth-detection.js +149 -0
  105. package/dist/utils/oauth-service.d.ts +88 -0
  106. package/dist/utils/oauth-service.d.ts.map +1 -0
  107. package/dist/utils/oauth-service.js +240 -0
  108. 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"}