@wener/mcps 1.0.1
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 +21 -0
- package/dist/index.mjs +15 -0
- package/dist/mcps-cli.mjs +174727 -0
- package/lib/chat/agent.js +187 -0
- package/lib/chat/agent.js.map +1 -0
- package/lib/chat/audit.js +238 -0
- package/lib/chat/audit.js.map +1 -0
- package/lib/chat/converters.js +467 -0
- package/lib/chat/converters.js.map +1 -0
- package/lib/chat/handler.js +1068 -0
- package/lib/chat/handler.js.map +1 -0
- package/lib/chat/index.js +12 -0
- package/lib/chat/index.js.map +1 -0
- package/lib/chat/types.js +35 -0
- package/lib/chat/types.js.map +1 -0
- package/lib/contracts/AuditContract.js +85 -0
- package/lib/contracts/AuditContract.js.map +1 -0
- package/lib/contracts/McpsContract.js +113 -0
- package/lib/contracts/McpsContract.js.map +1 -0
- package/lib/contracts/index.js +3 -0
- package/lib/contracts/index.js.map +1 -0
- package/lib/dev.server.js +7 -0
- package/lib/dev.server.js.map +1 -0
- package/lib/entities/ChatRequestEntity.js +318 -0
- package/lib/entities/ChatRequestEntity.js.map +1 -0
- package/lib/entities/McpRequestEntity.js +271 -0
- package/lib/entities/McpRequestEntity.js.map +1 -0
- package/lib/entities/RequestLogEntity.js +177 -0
- package/lib/entities/RequestLogEntity.js.map +1 -0
- package/lib/entities/ResponseEntity.js +150 -0
- package/lib/entities/ResponseEntity.js.map +1 -0
- package/lib/entities/index.js +11 -0
- package/lib/entities/index.js.map +1 -0
- package/lib/entities/types.js +11 -0
- package/lib/entities/types.js.map +1 -0
- package/lib/index.js +3 -0
- package/lib/index.js.map +1 -0
- package/lib/mcps-cli.js +44 -0
- package/lib/mcps-cli.js.map +1 -0
- package/lib/providers/McpServerHandlerDef.js +40 -0
- package/lib/providers/McpServerHandlerDef.js.map +1 -0
- package/lib/providers/findMcpServerDef.js +26 -0
- package/lib/providers/findMcpServerDef.js.map +1 -0
- package/lib/providers/prometheus/def.js +24 -0
- package/lib/providers/prometheus/def.js.map +1 -0
- package/lib/providers/prometheus/index.js +2 -0
- package/lib/providers/prometheus/index.js.map +1 -0
- package/lib/providers/relay/def.js +32 -0
- package/lib/providers/relay/def.js.map +1 -0
- package/lib/providers/relay/index.js +2 -0
- package/lib/providers/relay/index.js.map +1 -0
- package/lib/providers/sql/def.js +31 -0
- package/lib/providers/sql/def.js.map +1 -0
- package/lib/providers/sql/index.js +2 -0
- package/lib/providers/sql/index.js.map +1 -0
- package/lib/providers/tencent-cls/def.js +44 -0
- package/lib/providers/tencent-cls/def.js.map +1 -0
- package/lib/providers/tencent-cls/index.js +2 -0
- package/lib/providers/tencent-cls/index.js.map +1 -0
- package/lib/scripts/bundle.js +90 -0
- package/lib/scripts/bundle.js.map +1 -0
- package/lib/server/api-routes.js +96 -0
- package/lib/server/api-routes.js.map +1 -0
- package/lib/server/audit.js +274 -0
- package/lib/server/audit.js.map +1 -0
- package/lib/server/chat-routes.js +82 -0
- package/lib/server/chat-routes.js.map +1 -0
- package/lib/server/config.js +223 -0
- package/lib/server/config.js.map +1 -0
- package/lib/server/db.js +97 -0
- package/lib/server/db.js.map +1 -0
- package/lib/server/index.js +2 -0
- package/lib/server/index.js.map +1 -0
- package/lib/server/mcp-handler.js +167 -0
- package/lib/server/mcp-handler.js.map +1 -0
- package/lib/server/mcp-routes.js +112 -0
- package/lib/server/mcp-routes.js.map +1 -0
- package/lib/server/mcps-router.js +119 -0
- package/lib/server/mcps-router.js.map +1 -0
- package/lib/server/schema.js +129 -0
- package/lib/server/schema.js.map +1 -0
- package/lib/server/server.js +166 -0
- package/lib/server/server.js.map +1 -0
- package/lib/web/ChatPage.js +827 -0
- package/lib/web/ChatPage.js.map +1 -0
- package/lib/web/McpInspectorPage.js +214 -0
- package/lib/web/McpInspectorPage.js.map +1 -0
- package/lib/web/ServersPage.js +93 -0
- package/lib/web/ServersPage.js.map +1 -0
- package/lib/web/main.js +541 -0
- package/lib/web/main.js.map +1 -0
- package/package.json +83 -0
- package/src/chat/agent.ts +240 -0
- package/src/chat/audit.ts +377 -0
- package/src/chat/converters.test.ts +325 -0
- package/src/chat/converters.ts +459 -0
- package/src/chat/handler.test.ts +137 -0
- package/src/chat/handler.ts +1233 -0
- package/src/chat/index.ts +16 -0
- package/src/chat/types.ts +72 -0
- package/src/contracts/AuditContract.ts +93 -0
- package/src/contracts/McpsContract.ts +141 -0
- package/src/contracts/index.ts +18 -0
- package/src/dev.server.ts +7 -0
- package/src/entities/ChatRequestEntity.ts +157 -0
- package/src/entities/McpRequestEntity.ts +149 -0
- package/src/entities/RequestLogEntity.ts +78 -0
- package/src/entities/ResponseEntity.ts +75 -0
- package/src/entities/index.ts +12 -0
- package/src/entities/types.ts +188 -0
- package/src/index.ts +1 -0
- package/src/mcps-cli.ts +59 -0
- package/src/providers/McpServerHandlerDef.ts +105 -0
- package/src/providers/findMcpServerDef.ts +31 -0
- package/src/providers/prometheus/def.ts +21 -0
- package/src/providers/prometheus/index.ts +1 -0
- package/src/providers/relay/def.ts +31 -0
- package/src/providers/relay/index.ts +1 -0
- package/src/providers/relay/relay.test.ts +47 -0
- package/src/providers/sql/def.ts +33 -0
- package/src/providers/sql/index.ts +1 -0
- package/src/providers/tencent-cls/def.ts +38 -0
- package/src/providers/tencent-cls/index.ts +1 -0
- package/src/scripts/bundle.ts +82 -0
- package/src/server/api-routes.ts +98 -0
- package/src/server/audit.ts +310 -0
- package/src/server/chat-routes.ts +95 -0
- package/src/server/config.test.ts +162 -0
- package/src/server/config.ts +198 -0
- package/src/server/db.ts +115 -0
- package/src/server/index.ts +1 -0
- package/src/server/mcp-handler.ts +209 -0
- package/src/server/mcp-routes.ts +133 -0
- package/src/server/mcps-router.ts +133 -0
- package/src/server/schema.ts +175 -0
- package/src/server/server.ts +163 -0
- package/src/web/ChatPage.tsx +1005 -0
- package/src/web/McpInspectorPage.tsx +254 -0
- package/src/web/ServersPage.tsx +139 -0
- package/src/web/main.tsx +600 -0
- package/src/web/styles.css +15 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat API Module
|
|
3
|
+
* Provides unified AI model gateway with protocol conversion
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Types
|
|
7
|
+
export * from './types';
|
|
8
|
+
|
|
9
|
+
// Converters
|
|
10
|
+
export * from './converters';
|
|
11
|
+
|
|
12
|
+
// Audit
|
|
13
|
+
export * from './audit';
|
|
14
|
+
|
|
15
|
+
// Handler
|
|
16
|
+
export { createChatHandler, type ChatHandlerOptions } from './handler';
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common types for chat API
|
|
3
|
+
*/
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Provider Configuration (wener-mcps specific)
|
|
8
|
+
// ============================================================================
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Protocol type for model providers
|
|
12
|
+
*/
|
|
13
|
+
export type ProtocolType = 'openai' | 'anthropic' | 'gemini';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Provider endpoint configuration
|
|
17
|
+
*/
|
|
18
|
+
export const ProviderEndpointSchema = z.object({
|
|
19
|
+
baseUrl: z.string(),
|
|
20
|
+
headers: z.record(z.string(), z.string()).optional(),
|
|
21
|
+
processors: z.array(z.string()).optional(),
|
|
22
|
+
});
|
|
23
|
+
export type ProviderEndpoint = z.infer<typeof ProviderEndpointSchema>;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Model configuration
|
|
27
|
+
*/
|
|
28
|
+
export const ModelConfigSchema = z.object({
|
|
29
|
+
/** Base URL for the API */
|
|
30
|
+
baseUrl: z.string().optional(),
|
|
31
|
+
/** API key (uses Authorization: Bearer header) */
|
|
32
|
+
apiKey: z.string().optional(),
|
|
33
|
+
/** Additional headers */
|
|
34
|
+
headers: z.record(z.string(), z.string()).optional(),
|
|
35
|
+
/** Default adapter for protocol conversion */
|
|
36
|
+
adapter: z.enum(['openai', 'anthropic', 'gemini']).optional(),
|
|
37
|
+
/** Adapter-specific endpoints */
|
|
38
|
+
adapters: z
|
|
39
|
+
.object({
|
|
40
|
+
openai: ProviderEndpointSchema.optional(),
|
|
41
|
+
anthropic: ProviderEndpointSchema.optional(),
|
|
42
|
+
gemini: ProviderEndpointSchema.optional(),
|
|
43
|
+
})
|
|
44
|
+
.optional(),
|
|
45
|
+
/** Processor chain */
|
|
46
|
+
processors: z.array(z.string()).optional(),
|
|
47
|
+
});
|
|
48
|
+
export type ModelConfig = z.infer<typeof ModelConfigSchema>;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Chat configuration with models
|
|
52
|
+
*/
|
|
53
|
+
export const ChatConfigSchema = z.object({
|
|
54
|
+
models: z.record(z.string(), ModelConfigSchema).optional(),
|
|
55
|
+
});
|
|
56
|
+
export type ChatConfig = z.infer<typeof ChatConfigSchema>;
|
|
57
|
+
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// Stream Event Types
|
|
60
|
+
// ============================================================================
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Stream event types for SSE
|
|
64
|
+
*/
|
|
65
|
+
export type StreamEventType =
|
|
66
|
+
| 'message_start'
|
|
67
|
+
| 'content_block_start'
|
|
68
|
+
| 'content_block_delta'
|
|
69
|
+
| 'content_block_stop'
|
|
70
|
+
| 'message_delta'
|
|
71
|
+
| 'message_stop'
|
|
72
|
+
| 'error';
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { oc } from '@orpc/contract';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
// Audit event schema
|
|
5
|
+
export const AuditEventSchema = z.object({
|
|
6
|
+
id: z.string(),
|
|
7
|
+
timestamp: z.string(),
|
|
8
|
+
method: z.string(),
|
|
9
|
+
path: z.string(),
|
|
10
|
+
serverName: z.string().nullish(),
|
|
11
|
+
serverType: z.string().nullish(),
|
|
12
|
+
status: z.number().nullish(),
|
|
13
|
+
durationMs: z.number().nullish(),
|
|
14
|
+
requestHeaders: z.record(z.string(), z.string()).nullish(),
|
|
15
|
+
responseHeaders: z.record(z.string(), z.string()).nullish(),
|
|
16
|
+
requestBody: z.unknown().nullish(),
|
|
17
|
+
responseBody: z.unknown().nullish(),
|
|
18
|
+
error: z.string().nullish(),
|
|
19
|
+
toolName: z.string().nullish(),
|
|
20
|
+
toolArgs: z.unknown().nullish(),
|
|
21
|
+
});
|
|
22
|
+
export type AuditEvent = z.infer<typeof AuditEventSchema>;
|
|
23
|
+
|
|
24
|
+
// Query params
|
|
25
|
+
export const AuditQuerySchema = z.object({
|
|
26
|
+
limit: z.coerce.number().default(50),
|
|
27
|
+
offset: z.coerce.number().default(0),
|
|
28
|
+
serverName: z.string().nullish(),
|
|
29
|
+
serverType: z.string().nullish(),
|
|
30
|
+
method: z.string().nullish(),
|
|
31
|
+
from: z.string().nullish(),
|
|
32
|
+
to: z.string().nullish(),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Audit stats
|
|
36
|
+
export const AuditStatsSchema = z.object({
|
|
37
|
+
totalRequests: z.number(),
|
|
38
|
+
totalErrors: z.number(),
|
|
39
|
+
avgDurationMs: z.number(),
|
|
40
|
+
byServer: z.array(
|
|
41
|
+
z.object({
|
|
42
|
+
name: z.string(),
|
|
43
|
+
count: z.number(),
|
|
44
|
+
}),
|
|
45
|
+
),
|
|
46
|
+
byMethod: z.array(
|
|
47
|
+
z.object({
|
|
48
|
+
method: z.string(),
|
|
49
|
+
count: z.number(),
|
|
50
|
+
}),
|
|
51
|
+
),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Contract definition
|
|
55
|
+
export const AuditContract = oc.prefix('/audit').router({
|
|
56
|
+
// List audit events
|
|
57
|
+
list: oc
|
|
58
|
+
.input(AuditQuerySchema)
|
|
59
|
+
.output(
|
|
60
|
+
z.object({
|
|
61
|
+
events: z.array(AuditEventSchema),
|
|
62
|
+
total: z.number(),
|
|
63
|
+
}),
|
|
64
|
+
)
|
|
65
|
+
.route({ method: 'GET', path: '/', summary: 'List audit events' }),
|
|
66
|
+
|
|
67
|
+
// Get single event
|
|
68
|
+
get: oc
|
|
69
|
+
.input(z.object({ id: z.string() }))
|
|
70
|
+
.output(AuditEventSchema.nullable())
|
|
71
|
+
.route({ method: 'GET', path: '/{id}', summary: 'Get audit event by ID' }),
|
|
72
|
+
|
|
73
|
+
// Get stats
|
|
74
|
+
stats: oc
|
|
75
|
+
.input(
|
|
76
|
+
z.object({
|
|
77
|
+
from: z.string().nullish(),
|
|
78
|
+
to: z.string().nullish(),
|
|
79
|
+
}),
|
|
80
|
+
)
|
|
81
|
+
.output(AuditStatsSchema)
|
|
82
|
+
.route({ method: 'GET', path: '/stats', summary: 'Get audit statistics' }),
|
|
83
|
+
|
|
84
|
+
// Clear old events
|
|
85
|
+
clear: oc
|
|
86
|
+
.input(
|
|
87
|
+
z.object({
|
|
88
|
+
before: z.string().describe('Clear events before this timestamp'),
|
|
89
|
+
}),
|
|
90
|
+
)
|
|
91
|
+
.output(z.object({ deleted: z.number() }))
|
|
92
|
+
.route({ method: 'DELETE', path: '/', summary: 'Clear audit events' }),
|
|
93
|
+
});
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { oc } from '@orpc/contract';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
// Server info schema
|
|
5
|
+
export const ServerInfoSchema = z.object({
|
|
6
|
+
name: z.string(),
|
|
7
|
+
type: z.string(),
|
|
8
|
+
disabled: z.boolean().optional(),
|
|
9
|
+
});
|
|
10
|
+
export type ServerInfo = z.infer<typeof ServerInfoSchema>;
|
|
11
|
+
|
|
12
|
+
// Server type info schema
|
|
13
|
+
export const ServerTypeInfoSchema = z.object({
|
|
14
|
+
type: z.string(),
|
|
15
|
+
description: z.string(),
|
|
16
|
+
dynamicEndpoint: z.string(),
|
|
17
|
+
});
|
|
18
|
+
export type ServerTypeInfo = z.infer<typeof ServerTypeInfoSchema>;
|
|
19
|
+
|
|
20
|
+
// Model info schema
|
|
21
|
+
export const ModelInfoSchema = z.object({
|
|
22
|
+
name: z.string(),
|
|
23
|
+
adapter: z.string().nullish(),
|
|
24
|
+
baseUrl: z.string().nullish(),
|
|
25
|
+
contextWindow: z.number().nullish(),
|
|
26
|
+
maxInputTokens: z.number().nullish(),
|
|
27
|
+
maxOutputTokens: z.number().nullish(),
|
|
28
|
+
});
|
|
29
|
+
export type ModelInfo = z.infer<typeof ModelInfoSchema>;
|
|
30
|
+
|
|
31
|
+
// Service overview schema
|
|
32
|
+
export const ServiceOverviewSchema = z.object({
|
|
33
|
+
name: z.string(),
|
|
34
|
+
version: z.string(),
|
|
35
|
+
servers: z.array(ServerInfoSchema),
|
|
36
|
+
serverTypes: z.array(ServerTypeInfoSchema),
|
|
37
|
+
models: z.array(ModelInfoSchema),
|
|
38
|
+
endpoints: z.array(z.string()),
|
|
39
|
+
});
|
|
40
|
+
export type ServiceOverview = z.infer<typeof ServiceOverviewSchema>;
|
|
41
|
+
|
|
42
|
+
// Request stats schema
|
|
43
|
+
export const RequestStatsSchema = z.object({
|
|
44
|
+
totalRequests: z.number(),
|
|
45
|
+
totalErrors: z.number(),
|
|
46
|
+
avgDurationMs: z.number(),
|
|
47
|
+
byServer: z.array(
|
|
48
|
+
z.object({
|
|
49
|
+
name: z.string(),
|
|
50
|
+
count: z.number(),
|
|
51
|
+
}),
|
|
52
|
+
),
|
|
53
|
+
byMethod: z.array(
|
|
54
|
+
z.object({
|
|
55
|
+
method: z.string(),
|
|
56
|
+
count: z.number(),
|
|
57
|
+
}),
|
|
58
|
+
),
|
|
59
|
+
byEndpoint: z.array(
|
|
60
|
+
z.object({
|
|
61
|
+
endpoint: z.string(),
|
|
62
|
+
count: z.number(),
|
|
63
|
+
}),
|
|
64
|
+
),
|
|
65
|
+
});
|
|
66
|
+
export type RequestStats = z.infer<typeof RequestStatsSchema>;
|
|
67
|
+
|
|
68
|
+
// Tool parameter schema
|
|
69
|
+
export const ToolParameterSchema = z.object({
|
|
70
|
+
name: z.string(),
|
|
71
|
+
type: z.string(),
|
|
72
|
+
description: z.string().nullish(),
|
|
73
|
+
required: z.boolean(),
|
|
74
|
+
});
|
|
75
|
+
export type ToolParameter = z.infer<typeof ToolParameterSchema>;
|
|
76
|
+
|
|
77
|
+
// Tool info schema for display
|
|
78
|
+
export const ToolInfoSchema = z.object({
|
|
79
|
+
name: z.string(),
|
|
80
|
+
description: z.string().nullish(),
|
|
81
|
+
serverName: z.string(),
|
|
82
|
+
serverType: z.string(),
|
|
83
|
+
parameters: z.array(ToolParameterSchema),
|
|
84
|
+
inputSchemaCompact: z.string().nullish(), // Compact TS-like schema representation
|
|
85
|
+
});
|
|
86
|
+
export type ToolInfo = z.infer<typeof ToolInfoSchema>;
|
|
87
|
+
|
|
88
|
+
// MCPS Contract
|
|
89
|
+
export const McpsContract = oc.prefix('/mcps').router({
|
|
90
|
+
// Get service overview
|
|
91
|
+
overview: oc
|
|
92
|
+
.input(z.object({}))
|
|
93
|
+
.output(ServiceOverviewSchema)
|
|
94
|
+
.route({ method: 'GET', path: '/overview', summary: 'Get service overview' }),
|
|
95
|
+
|
|
96
|
+
// Get request statistics
|
|
97
|
+
stats: oc
|
|
98
|
+
.input(
|
|
99
|
+
z.object({
|
|
100
|
+
from: z.string().nullish(),
|
|
101
|
+
to: z.string().nullish(),
|
|
102
|
+
}),
|
|
103
|
+
)
|
|
104
|
+
.output(RequestStatsSchema)
|
|
105
|
+
.route({ method: 'GET', path: '/stats', summary: 'Get request statistics' }),
|
|
106
|
+
|
|
107
|
+
// List configured servers
|
|
108
|
+
servers: oc
|
|
109
|
+
.input(z.object({}))
|
|
110
|
+
.output(
|
|
111
|
+
z.object({
|
|
112
|
+
servers: z.array(ServerInfoSchema),
|
|
113
|
+
}),
|
|
114
|
+
)
|
|
115
|
+
.route({ method: 'GET', path: '/servers', summary: 'List configured servers' }),
|
|
116
|
+
|
|
117
|
+
// List configured models
|
|
118
|
+
models: oc
|
|
119
|
+
.input(z.object({}))
|
|
120
|
+
.output(
|
|
121
|
+
z.object({
|
|
122
|
+
models: z.array(ModelInfoSchema),
|
|
123
|
+
}),
|
|
124
|
+
)
|
|
125
|
+
.route({ method: 'GET', path: '/models', summary: 'List configured models' }),
|
|
126
|
+
|
|
127
|
+
// List tools from all servers
|
|
128
|
+
tools: oc
|
|
129
|
+
.input(
|
|
130
|
+
z.object({
|
|
131
|
+
server: z.string().nullish(), // Filter by server name
|
|
132
|
+
filter: z.string().nullish(), // Glob pattern filter (like X-MCP-Include)
|
|
133
|
+
}),
|
|
134
|
+
)
|
|
135
|
+
.output(
|
|
136
|
+
z.object({
|
|
137
|
+
tools: z.array(ToolInfoSchema),
|
|
138
|
+
}),
|
|
139
|
+
)
|
|
140
|
+
.route({ method: 'GET', path: '/tools', summary: 'List tools from MCP servers' }),
|
|
141
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { AuditContract, AuditEventSchema, AuditQuerySchema, AuditStatsSchema, type AuditEvent } from './AuditContract';
|
|
2
|
+
export {
|
|
3
|
+
McpsContract,
|
|
4
|
+
ServiceOverviewSchema,
|
|
5
|
+
ServerInfoSchema,
|
|
6
|
+
ServerTypeInfoSchema,
|
|
7
|
+
ModelInfoSchema,
|
|
8
|
+
RequestStatsSchema,
|
|
9
|
+
ToolInfoSchema,
|
|
10
|
+
ToolParameterSchema,
|
|
11
|
+
type ServiceOverview,
|
|
12
|
+
type ServerInfo,
|
|
13
|
+
type ServerTypeInfo,
|
|
14
|
+
type ModelInfo,
|
|
15
|
+
type RequestStats,
|
|
16
|
+
type ToolInfo,
|
|
17
|
+
type ToolParameter,
|
|
18
|
+
} from './McpsContract';
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { Entity, Enum, PrimaryKey, Property } from '@mikro-orm/decorators/es';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Chat protocol type
|
|
5
|
+
*/
|
|
6
|
+
export const ChatProtocolType = Object.freeze({
|
|
7
|
+
OpenAI: 'openai',
|
|
8
|
+
Anthropic: 'anthropic',
|
|
9
|
+
Gemini: 'gemini',
|
|
10
|
+
} as const);
|
|
11
|
+
export type ChatProtocolType = (typeof ChatProtocolType)[keyof typeof ChatProtocolType];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Request status
|
|
15
|
+
*/
|
|
16
|
+
export const RequestStatus = Object.freeze({
|
|
17
|
+
Pending: 'pending',
|
|
18
|
+
Success: 'success',
|
|
19
|
+
Error: 'error',
|
|
20
|
+
Timeout: 'timeout',
|
|
21
|
+
} as const);
|
|
22
|
+
export type RequestStatus = (typeof RequestStatus)[keyof typeof RequestStatus];
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Chat Request Entity for auditing and metering
|
|
26
|
+
*/
|
|
27
|
+
@Entity({ tableName: 'chat_request' })
|
|
28
|
+
export class ChatRequestEntity {
|
|
29
|
+
@PrimaryKey({ type: 'integer' })
|
|
30
|
+
id!: number;
|
|
31
|
+
|
|
32
|
+
/** Unique request ID for tracing */
|
|
33
|
+
@Property({ type: 'string', unique: true })
|
|
34
|
+
requestId!: string;
|
|
35
|
+
|
|
36
|
+
/** Request timestamp */
|
|
37
|
+
@Property({ type: 'datetime' })
|
|
38
|
+
requestedAt: Date = new Date();
|
|
39
|
+
|
|
40
|
+
/** Response timestamp */
|
|
41
|
+
@Property({ type: 'datetime', nullable: true })
|
|
42
|
+
completedAt?: Date;
|
|
43
|
+
|
|
44
|
+
/** Request status */
|
|
45
|
+
@Enum(() => RequestStatus)
|
|
46
|
+
status: RequestStatus = RequestStatus.Pending;
|
|
47
|
+
|
|
48
|
+
/** HTTP method */
|
|
49
|
+
@Property({ type: 'string' })
|
|
50
|
+
method!: string;
|
|
51
|
+
|
|
52
|
+
/** Request path/endpoint */
|
|
53
|
+
@Property({ type: 'string' })
|
|
54
|
+
endpoint!: string;
|
|
55
|
+
|
|
56
|
+
/** Input protocol (client-facing) */
|
|
57
|
+
@Enum(() => ChatProtocolType)
|
|
58
|
+
inputProtocol!: ChatProtocolType;
|
|
59
|
+
|
|
60
|
+
/** Output protocol (upstream provider) */
|
|
61
|
+
@Enum(() => ChatProtocolType)
|
|
62
|
+
outputProtocol!: ChatProtocolType;
|
|
63
|
+
|
|
64
|
+
/** Model name requested */
|
|
65
|
+
@Property({ type: 'string' })
|
|
66
|
+
model!: string;
|
|
67
|
+
|
|
68
|
+
/** Resolved model name */
|
|
69
|
+
@Property({ type: 'string', nullable: true })
|
|
70
|
+
resolvedModel?: string;
|
|
71
|
+
|
|
72
|
+
/** Provider name */
|
|
73
|
+
@Property({ type: 'string', nullable: true })
|
|
74
|
+
provider?: string;
|
|
75
|
+
|
|
76
|
+
/** Upstream base URL */
|
|
77
|
+
@Property({ type: 'string', nullable: true })
|
|
78
|
+
upstreamUrl?: string;
|
|
79
|
+
|
|
80
|
+
/** Whether request was streaming */
|
|
81
|
+
@Property({ type: 'boolean', default: false })
|
|
82
|
+
streaming: boolean = false;
|
|
83
|
+
|
|
84
|
+
/** Input token count */
|
|
85
|
+
@Property({ type: 'integer', nullable: true })
|
|
86
|
+
inputTokens?: number;
|
|
87
|
+
|
|
88
|
+
/** Output token count */
|
|
89
|
+
@Property({ type: 'integer', nullable: true })
|
|
90
|
+
outputTokens?: number;
|
|
91
|
+
|
|
92
|
+
/** Total token count */
|
|
93
|
+
@Property({ type: 'integer', nullable: true })
|
|
94
|
+
totalTokens?: number;
|
|
95
|
+
|
|
96
|
+
/** Request duration in ms */
|
|
97
|
+
@Property({ type: 'integer', nullable: true })
|
|
98
|
+
durationMs?: number;
|
|
99
|
+
|
|
100
|
+
/** Time to first token in ms */
|
|
101
|
+
@Property({ type: 'integer', nullable: true })
|
|
102
|
+
ttftMs?: number;
|
|
103
|
+
|
|
104
|
+
/** HTTP status code */
|
|
105
|
+
@Property({ type: 'integer', nullable: true })
|
|
106
|
+
httpStatus?: number;
|
|
107
|
+
|
|
108
|
+
/** Error message */
|
|
109
|
+
@Property({ type: 'text', nullable: true })
|
|
110
|
+
errorMessage?: string;
|
|
111
|
+
|
|
112
|
+
/** Error code */
|
|
113
|
+
@Property({ type: 'string', nullable: true })
|
|
114
|
+
errorCode?: string;
|
|
115
|
+
|
|
116
|
+
/** Client IP */
|
|
117
|
+
@Property({ type: 'string', nullable: true })
|
|
118
|
+
clientIp?: string;
|
|
119
|
+
|
|
120
|
+
/** User agent */
|
|
121
|
+
@Property({ type: 'string', nullable: true })
|
|
122
|
+
userAgent?: string;
|
|
123
|
+
|
|
124
|
+
/** User ID */
|
|
125
|
+
@Property({ type: 'string', nullable: true })
|
|
126
|
+
userId?: string;
|
|
127
|
+
|
|
128
|
+
/** Organization ID */
|
|
129
|
+
@Property({ type: 'string', nullable: true })
|
|
130
|
+
orgId?: string;
|
|
131
|
+
|
|
132
|
+
/** API key ID (not the actual key) */
|
|
133
|
+
@Property({ type: 'string', nullable: true })
|
|
134
|
+
apiKeyId?: string;
|
|
135
|
+
|
|
136
|
+
/** Request metadata (JSON) */
|
|
137
|
+
@Property({ type: 'json', nullable: true })
|
|
138
|
+
requestMeta?: Record<string, unknown>;
|
|
139
|
+
|
|
140
|
+
/** Response metadata (JSON) */
|
|
141
|
+
@Property({ type: 'json', nullable: true })
|
|
142
|
+
responseMeta?: Record<string, unknown>;
|
|
143
|
+
|
|
144
|
+
/** Cost in credits (decimal string) */
|
|
145
|
+
@Property({ type: 'string', nullable: true })
|
|
146
|
+
cost?: string;
|
|
147
|
+
|
|
148
|
+
/** Currency */
|
|
149
|
+
@Property({ type: 'string', nullable: true })
|
|
150
|
+
currency?: string;
|
|
151
|
+
|
|
152
|
+
@Property({ type: 'datetime' })
|
|
153
|
+
createdAt: Date = new Date();
|
|
154
|
+
|
|
155
|
+
@Property({ type: 'datetime', onUpdate: () => new Date() })
|
|
156
|
+
updatedAt: Date = new Date();
|
|
157
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { Entity, Enum, PrimaryKey, Property } from '@mikro-orm/decorators/es';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* MCP server type
|
|
5
|
+
*/
|
|
6
|
+
export const McpServerType = Object.freeze({
|
|
7
|
+
TencentCls: 'tencent-cls',
|
|
8
|
+
Sql: 'sql',
|
|
9
|
+
Prometheus: 'prometheus',
|
|
10
|
+
Relay: 'relay',
|
|
11
|
+
Custom: 'custom',
|
|
12
|
+
} as const);
|
|
13
|
+
export type McpServerType = (typeof McpServerType)[keyof typeof McpServerType];
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* MCP request type (JSON-RPC method)
|
|
17
|
+
*/
|
|
18
|
+
export const McpRequestType = Object.freeze({
|
|
19
|
+
Initialize: 'initialize',
|
|
20
|
+
ToolsList: 'tools/list',
|
|
21
|
+
ToolsCall: 'tools/call',
|
|
22
|
+
ResourcesList: 'resources/list',
|
|
23
|
+
ResourcesRead: 'resources/read',
|
|
24
|
+
PromptsList: 'prompts/list',
|
|
25
|
+
PromptsGet: 'prompts/get',
|
|
26
|
+
CompletionComplete: 'completion/complete',
|
|
27
|
+
LoggingSetLevel: 'logging/setLevel',
|
|
28
|
+
Ping: 'ping',
|
|
29
|
+
Other: 'other',
|
|
30
|
+
} as const);
|
|
31
|
+
export type McpRequestType = (typeof McpRequestType)[keyof typeof McpRequestType];
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Request status
|
|
35
|
+
*/
|
|
36
|
+
export const RequestStatus = Object.freeze({
|
|
37
|
+
Pending: 'pending',
|
|
38
|
+
Success: 'success',
|
|
39
|
+
Error: 'error',
|
|
40
|
+
Timeout: 'timeout',
|
|
41
|
+
} as const);
|
|
42
|
+
export type RequestStatus = (typeof RequestStatus)[keyof typeof RequestStatus];
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* MCP Request Entity for auditing
|
|
46
|
+
*/
|
|
47
|
+
@Entity({ tableName: 'mcp_request' })
|
|
48
|
+
export class McpRequestEntity {
|
|
49
|
+
@PrimaryKey({ type: 'integer' })
|
|
50
|
+
id!: number;
|
|
51
|
+
|
|
52
|
+
/** Unique request ID */
|
|
53
|
+
@Property({ type: 'string' })
|
|
54
|
+
requestId!: string;
|
|
55
|
+
|
|
56
|
+
/** MCP session ID */
|
|
57
|
+
@Property({ type: 'string', nullable: true })
|
|
58
|
+
sessionId?: string;
|
|
59
|
+
|
|
60
|
+
/** Request timestamp */
|
|
61
|
+
@Property({ type: 'datetime' })
|
|
62
|
+
requestedAt: Date = new Date();
|
|
63
|
+
|
|
64
|
+
/** Response timestamp */
|
|
65
|
+
@Property({ type: 'datetime', nullable: true })
|
|
66
|
+
completedAt?: Date;
|
|
67
|
+
|
|
68
|
+
/** Request status */
|
|
69
|
+
@Enum(() => RequestStatus)
|
|
70
|
+
status: RequestStatus = RequestStatus.Pending;
|
|
71
|
+
|
|
72
|
+
/** HTTP method */
|
|
73
|
+
@Property({ type: 'string' })
|
|
74
|
+
method!: string;
|
|
75
|
+
|
|
76
|
+
/** Request path */
|
|
77
|
+
@Property({ type: 'string' })
|
|
78
|
+
path!: string;
|
|
79
|
+
|
|
80
|
+
/** MCP server name */
|
|
81
|
+
@Property({ type: 'string' })
|
|
82
|
+
serverName!: string;
|
|
83
|
+
|
|
84
|
+
/** MCP server type */
|
|
85
|
+
@Enum(() => McpServerType)
|
|
86
|
+
serverType: McpServerType = McpServerType.Custom;
|
|
87
|
+
|
|
88
|
+
/** MCP request type (JSON-RPC method) */
|
|
89
|
+
@Enum(() => McpRequestType)
|
|
90
|
+
mcpMethod: McpRequestType = McpRequestType.Other;
|
|
91
|
+
|
|
92
|
+
/** Tool name (for tools/call) */
|
|
93
|
+
@Property({ type: 'string', nullable: true })
|
|
94
|
+
toolName?: string;
|
|
95
|
+
|
|
96
|
+
/** Resource URI (for resources/read) */
|
|
97
|
+
@Property({ type: 'string', nullable: true })
|
|
98
|
+
resourceUri?: string;
|
|
99
|
+
|
|
100
|
+
/** Prompt name (for prompts/get) */
|
|
101
|
+
@Property({ type: 'string', nullable: true })
|
|
102
|
+
promptName?: string;
|
|
103
|
+
|
|
104
|
+
/** Request duration in ms */
|
|
105
|
+
@Property({ type: 'integer', nullable: true })
|
|
106
|
+
durationMs?: number;
|
|
107
|
+
|
|
108
|
+
/** HTTP status code */
|
|
109
|
+
@Property({ type: 'integer', nullable: true })
|
|
110
|
+
httpStatus?: number;
|
|
111
|
+
|
|
112
|
+
/** Error message */
|
|
113
|
+
@Property({ type: 'text', nullable: true })
|
|
114
|
+
errorMessage?: string;
|
|
115
|
+
|
|
116
|
+
/** Error code */
|
|
117
|
+
@Property({ type: 'string', nullable: true })
|
|
118
|
+
errorCode?: string;
|
|
119
|
+
|
|
120
|
+
/** Client IP */
|
|
121
|
+
@Property({ type: 'string', nullable: true })
|
|
122
|
+
clientIp?: string;
|
|
123
|
+
|
|
124
|
+
/** User agent */
|
|
125
|
+
@Property({ type: 'string', nullable: true })
|
|
126
|
+
userAgent?: string;
|
|
127
|
+
|
|
128
|
+
/** User ID */
|
|
129
|
+
@Property({ type: 'string', nullable: true })
|
|
130
|
+
userId?: string;
|
|
131
|
+
|
|
132
|
+
/** Request headers (JSON) */
|
|
133
|
+
@Property({ type: 'json', nullable: true })
|
|
134
|
+
requestHeaders?: Record<string, string>;
|
|
135
|
+
|
|
136
|
+
/** Request body (JSON) */
|
|
137
|
+
@Property({ type: 'json', nullable: true })
|
|
138
|
+
requestBody?: Record<string, unknown>;
|
|
139
|
+
|
|
140
|
+
/** Response metadata (JSON) */
|
|
141
|
+
@Property({ type: 'json', nullable: true })
|
|
142
|
+
responseMeta?: Record<string, unknown>;
|
|
143
|
+
|
|
144
|
+
@Property({ type: 'datetime' })
|
|
145
|
+
createdAt: Date = new Date();
|
|
146
|
+
|
|
147
|
+
@Property({ type: 'datetime', onUpdate: () => new Date() })
|
|
148
|
+
updatedAt: Date = new Date();
|
|
149
|
+
}
|