@wener/mcps 1.0.2 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +144 -0
- package/dist/index.mjs +213076 -1
- package/dist/mcps-cli.mjs +102632 -59429
- package/lib/audit/AuditContract.js.map +1 -0
- package/lib/{chat/audit.js → audit/chat.js} +1 -1
- package/lib/audit/chat.js.map +1 -0
- package/lib/audit/entities/ChatRequestEntity.js.map +1 -0
- package/lib/audit/entities/McpRequestEntity.js.map +1 -0
- package/lib/audit/entities/RequestLogEntity.js.map +1 -0
- package/lib/audit/entities/ResponseEntity.js.map +1 -0
- package/lib/audit/entities/index.js +6 -0
- package/lib/audit/entities/index.js.map +1 -0
- package/lib/audit/server/db.js +64 -0
- package/lib/audit/server/db.js.map +1 -0
- package/lib/audit/server/index.js +2 -0
- package/lib/audit/server/index.js.map +1 -0
- package/lib/{server/audit.js → audit/server/plugin.js} +73 -127
- package/lib/audit/server/plugin.js.map +1 -0
- package/lib/audit/types.js.map +1 -0
- package/lib/chat/handler.js +5 -5
- package/lib/chat/handler.js.map +1 -1
- package/lib/chat/index.js +1 -1
- package/lib/chat/index.js.map +1 -1
- package/lib/cli-start.js +36 -0
- package/lib/cli-start.js.map +1 -0
- package/lib/cli.js +19 -0
- package/lib/cli.js.map +1 -0
- package/lib/contracts/index.js +1 -1
- package/lib/contracts/index.js.map +1 -1
- package/lib/dev.server.js +7 -1
- package/lib/dev.server.js.map +1 -1
- package/lib/entities/index.js +2 -10
- package/lib/entities/index.js.map +1 -1
- package/lib/index.js +21 -3
- package/lib/index.js.map +1 -1
- package/lib/mcps-cli.js +6 -35
- package/lib/mcps-cli.js.map +1 -1
- package/lib/providers/feishu/def.js +35 -0
- package/lib/providers/feishu/def.js.map +1 -0
- package/lib/providers/findMcpServerDef.js +1 -0
- package/lib/providers/findMcpServerDef.js.map +1 -1
- package/lib/scripts/bundle.js +7 -1
- package/lib/scripts/bundle.js.map +1 -1
- package/lib/server/api-routes.js +7 -8
- package/lib/server/api-routes.js.map +1 -1
- package/lib/server/events.js +13 -0
- package/lib/server/events.js.map +1 -0
- package/lib/server/mcp-routes.js +31 -60
- package/lib/server/mcp-routes.js.map +1 -1
- package/lib/server/mcps-router.js +19 -24
- package/lib/server/mcps-router.js.map +1 -1
- package/lib/server/schema.js +22 -2
- package/lib/server/schema.js.map +1 -1
- package/lib/server/server.js +142 -87
- package/lib/server/server.js.map +1 -1
- package/package.json +145 -85
- package/src/{chat/audit.ts → audit/chat.ts} +3 -3
- package/src/audit/entities/index.ts +6 -0
- package/src/audit/server/db.ts +65 -0
- package/src/audit/server/index.ts +8 -0
- package/src/{server/audit.ts → audit/server/plugin.ts} +71 -144
- package/src/chat/handler.ts +5 -5
- package/src/chat/index.ts +1 -1
- package/src/cli-start.ts +43 -0
- package/src/cli.ts +45 -0
- package/src/contracts/index.ts +1 -1
- package/src/dev.server.ts +8 -1
- package/src/entities/index.ts +2 -12
- package/src/index.ts +47 -1
- package/src/mcps-cli.ts +6 -48
- package/src/providers/feishu/def.ts +37 -0
- package/src/providers/findMcpServerDef.ts +1 -0
- package/src/scripts/bundle.ts +12 -1
- package/src/server/api-routes.ts +11 -8
- package/src/server/events.ts +29 -0
- package/src/server/mcp-routes.ts +30 -58
- package/src/server/mcps-router.ts +21 -29
- package/src/server/schema.ts +23 -2
- package/src/server/server.ts +149 -81
- package/LICENSE +0 -21
- package/lib/chat/audit.js.map +0 -1
- package/lib/contracts/AuditContract.js.map +0 -1
- package/lib/entities/ChatRequestEntity.js.map +0 -1
- package/lib/entities/McpRequestEntity.js.map +0 -1
- package/lib/entities/RequestLogEntity.js.map +0 -1
- package/lib/entities/ResponseEntity.js.map +0 -1
- package/lib/entities/types.js.map +0 -1
- package/lib/server/audit.js.map +0 -1
- package/lib/server/db.js +0 -97
- package/lib/server/db.js.map +0 -1
- package/src/server/db.ts +0 -115
- /package/lib/{contracts → audit}/AuditContract.js +0 -0
- /package/lib/{entities → audit/entities}/ChatRequestEntity.js +0 -0
- /package/lib/{entities → audit/entities}/McpRequestEntity.js +0 -0
- /package/lib/{entities → audit/entities}/RequestLogEntity.js +0 -0
- /package/lib/{entities → audit/entities}/ResponseEntity.js +0 -0
- /package/lib/{entities → audit}/types.js +0 -0
- /package/src/{contracts → audit}/AuditContract.ts +0 -0
- /package/src/{entities → audit/entities}/ChatRequestEntity.ts +0 -0
- /package/src/{entities → audit/entities}/McpRequestEntity.ts +0 -0
- /package/src/{entities → audit/entities}/RequestLogEntity.ts +0 -0
- /package/src/{entities → audit/entities}/ResponseEntity.ts +0 -0
- /package/src/{entities → audit}/types.ts +0 -0
package/src/scripts/bundle.ts
CHANGED
|
@@ -39,7 +39,18 @@ const commonOptions: esbuild.BuildOptions = {
|
|
|
39
39
|
sourcemap: false,
|
|
40
40
|
legalComments: 'none',
|
|
41
41
|
// External native modules
|
|
42
|
-
external: [
|
|
42
|
+
external: [
|
|
43
|
+
'better-sqlite3',
|
|
44
|
+
'bun:sqlite',
|
|
45
|
+
'kysely-bun-sqlite',
|
|
46
|
+
'oracledb',
|
|
47
|
+
'mariadb/callback',
|
|
48
|
+
'mysql',
|
|
49
|
+
'@nestjs/websockets',
|
|
50
|
+
'@nestjs/microservices',
|
|
51
|
+
'@nestjs/platform-express',
|
|
52
|
+
'@larksuiteoapi/node-sdk',
|
|
53
|
+
],
|
|
43
54
|
};
|
|
44
55
|
|
|
45
56
|
// Ensure dist directory exists
|
package/src/server/api-routes.ts
CHANGED
|
@@ -6,26 +6,29 @@ import { CORSPlugin } from '@orpc/server/plugins';
|
|
|
6
6
|
import { ZodToJsonSchemaConverter } from '@orpc/zod/zod4';
|
|
7
7
|
import type { Hono } from 'hono';
|
|
8
8
|
import { html } from 'hono/html';
|
|
9
|
-
import { AuditRouter } from './audit';
|
|
10
9
|
import { createMcpsRouter } from './mcps-router';
|
|
11
10
|
import type { McpsConfig } from './schema';
|
|
11
|
+
import type { StatsProvider } from './server';
|
|
12
12
|
|
|
13
13
|
export interface RegisterApiRoutesOptions {
|
|
14
14
|
app: Hono;
|
|
15
15
|
config: McpsConfig;
|
|
16
|
+
/** Additional oRPC routers registered by plugins (e.g. audit) */
|
|
17
|
+
apiRouters?: Record<string, any>;
|
|
18
|
+
/** Optional stats provider from audit plugin */
|
|
19
|
+
statsProvider?: StatsProvider;
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
/**
|
|
19
|
-
* Register oRPC API routes for
|
|
23
|
+
* Register oRPC API routes for MCPS.
|
|
24
|
+
* Audit router is not included by default - use setupAudit() plugin to add it.
|
|
20
25
|
*/
|
|
21
|
-
export function registerApiRoutes({ app, config }: RegisterApiRoutesOptions) {
|
|
22
|
-
|
|
23
|
-
const McpsRouter = createMcpsRouter({ config });
|
|
26
|
+
export function registerApiRoutes({ app, config, apiRouters, statsProvider }: RegisterApiRoutesOptions) {
|
|
27
|
+
const McpsRouter = createMcpsRouter({ config, statsProvider });
|
|
24
28
|
|
|
25
|
-
|
|
26
|
-
const combinedRouter = {
|
|
27
|
-
audit: AuditRouter,
|
|
29
|
+
const combinedRouter: Record<string, any> = {
|
|
28
30
|
mcps: McpsRouter,
|
|
31
|
+
...apiRouters,
|
|
29
32
|
};
|
|
30
33
|
|
|
31
34
|
const handleByRpc = new RPCHandler(combinedRouter);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import Emittery from 'emittery';
|
|
2
|
+
|
|
3
|
+
export const McpsEventType = {
|
|
4
|
+
Request: 'Mcps:Request',
|
|
5
|
+
} as const;
|
|
6
|
+
|
|
7
|
+
export type McpsRequestEvent = {
|
|
8
|
+
timestamp: string;
|
|
9
|
+
method: string;
|
|
10
|
+
path: string;
|
|
11
|
+
serverName?: string;
|
|
12
|
+
serverType?: string;
|
|
13
|
+
status?: number;
|
|
14
|
+
durationMs?: number;
|
|
15
|
+
error?: string;
|
|
16
|
+
requestHeaders?: Record<string, string>;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type McpsEventData = {
|
|
20
|
+
[McpsEventType.Request]: McpsRequestEvent;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type McpsEmitter = Emittery<McpsEventData>;
|
|
24
|
+
|
|
25
|
+
export function createMcpsEmitter(): McpsEmitter {
|
|
26
|
+
return new Emittery<McpsEventData>({
|
|
27
|
+
debug: { name: 'McpsEmitter' },
|
|
28
|
+
});
|
|
29
|
+
}
|
package/src/server/mcp-routes.ts
CHANGED
|
@@ -17,13 +17,15 @@ export interface RegisterMcpRoutesOptions {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
* Register MCP routes for both pre-configured and dynamic endpoints
|
|
20
|
+
* Register MCP routes for both pre-configured and dynamic endpoints.
|
|
21
|
+
*
|
|
22
|
+
* McpServer only supports one transport connection at a time, so we create
|
|
23
|
+
* a fresh server instance per request instead of caching stateful servers.
|
|
21
24
|
*/
|
|
22
|
-
export function registerMcpRoutes({ app, config, serverCache }: RegisterMcpRoutesOptions) {
|
|
25
|
+
export function registerMcpRoutes({ app, config, serverCache: _serverCache }: RegisterMcpRoutesOptions) {
|
|
23
26
|
const serverDefs = findMcpServerDef();
|
|
24
27
|
|
|
25
28
|
// Register pre-configured servers from config
|
|
26
|
-
// These are named endpoints like /mcp/my-sql that use config from file
|
|
27
29
|
for (const [name, serverConfig] of Object.entries(config.servers)) {
|
|
28
30
|
const def = getMcpServerHandlerDef(serverConfig.type);
|
|
29
31
|
if (!def) {
|
|
@@ -31,7 +33,6 @@ export function registerMcpRoutes({ app, config, serverCache }: RegisterMcpRoute
|
|
|
31
33
|
continue;
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
// Resolve config using def (config comes from file, not headers)
|
|
35
36
|
const options = def.resolveConfig(serverConfig);
|
|
36
37
|
if (!options) {
|
|
37
38
|
log.warn(`Failed to resolve config for ${name}`);
|
|
@@ -44,48 +45,23 @@ export function registerMcpRoutes({ app, config, serverCache }: RegisterMcpRoute
|
|
|
44
45
|
continue;
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
// Create and cache the server instance at startup
|
|
48
|
-
const cacheKey = `config::${name}`;
|
|
49
|
-
const item = def.create(options);
|
|
50
|
-
if (!item) {
|
|
51
|
-
log.warn(`Failed to create server: ${name}`);
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
serverCache.set(cacheKey, item);
|
|
55
|
-
|
|
56
48
|
const path = `/mcp/${name}`;
|
|
57
49
|
log.info(`Registered MCP server: ${path} (${serverConfig.type})`);
|
|
58
50
|
|
|
59
51
|
app.all(path, async (c) => {
|
|
60
|
-
|
|
61
|
-
if (!serverItem) {
|
|
62
|
-
return c.text('Server not found', 404);
|
|
63
|
-
}
|
|
64
|
-
// Create a new transport for each request to avoid "Transport already started" error
|
|
65
|
-
const transport = new StreamableHTTPTransport();
|
|
66
|
-
try {
|
|
67
|
-
await serverItem.server.connect(transport);
|
|
68
|
-
const handleRequest = createMcpLoggingHandler(transport, name);
|
|
69
|
-
return await handleRequest(c);
|
|
70
|
-
} catch (e) {
|
|
71
|
-
log.error(`[${name}] Request error:`, e);
|
|
72
|
-
return c.text(`Internal server error: ${e instanceof Error ? e.message : 'Unknown error'}`, 500);
|
|
73
|
-
}
|
|
52
|
+
return handleMcpRequest(c, def, options, name);
|
|
74
53
|
});
|
|
75
54
|
}
|
|
76
55
|
|
|
77
|
-
// Register dynamic endpoints for all server types
|
|
78
|
-
// These endpoints accept config via HTTP headers
|
|
56
|
+
// Register dynamic endpoints for all server types (header-based config)
|
|
79
57
|
for (const def of serverDefs) {
|
|
80
58
|
const path = `/mcp/${def.name}`;
|
|
81
59
|
log.debug(`Registering dynamic endpoint: ${path}`);
|
|
82
60
|
|
|
83
61
|
app.all(path, async (c) => {
|
|
84
|
-
// Use def.resolveConfig to parse config from headers
|
|
85
62
|
const options = def.resolveConfig({ type: def.name } as any, c.req.raw.headers);
|
|
86
63
|
|
|
87
64
|
if (!options) {
|
|
88
|
-
// Build error message from headerMappings
|
|
89
65
|
const requiredHeaders =
|
|
90
66
|
def.headerMappings
|
|
91
67
|
?.filter((m) => m.required)
|
|
@@ -94,40 +70,36 @@ export function registerMcpRoutes({ app, config, serverCache }: RegisterMcpRoute
|
|
|
94
70
|
return c.text(`Missing ${requiredHeaders}`, 400);
|
|
95
71
|
}
|
|
96
72
|
|
|
97
|
-
// Validate options
|
|
98
73
|
const validation = def.validateOptions(options);
|
|
99
74
|
if (!validation.valid) {
|
|
100
75
|
return c.text(validation.error || `Invalid configuration for ${def.name}`, 400);
|
|
101
76
|
}
|
|
102
77
|
|
|
103
|
-
|
|
104
|
-
const key = def.getCacheKey(options);
|
|
105
|
-
let item = serverCache.get(key);
|
|
106
|
-
if (!item) {
|
|
107
|
-
log.info(`Creating new ${def.title} server: ${key}`);
|
|
108
|
-
try {
|
|
109
|
-
const newItem = def.create(options);
|
|
110
|
-
if (!newItem) return c.text(`Failed to create ${def.name} server`, 500);
|
|
111
|
-
item = newItem;
|
|
112
|
-
serverCache.set(key, item);
|
|
113
|
-
} catch (e) {
|
|
114
|
-
log.error(`Failed to create ${def.name} server:`, e);
|
|
115
|
-
return c.text(`Failed to create ${def.name} server`, 500);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Create a new transport for each request
|
|
120
|
-
const transport = new StreamableHTTPTransport();
|
|
121
|
-
try {
|
|
122
|
-
await item.server.connect(transport);
|
|
123
|
-
const handleRequest = createMcpLoggingHandler(transport, def.name);
|
|
124
|
-
return await handleRequest(c);
|
|
125
|
-
} catch (e) {
|
|
126
|
-
log.error(`[${def.name}] Request error:`, e);
|
|
127
|
-
return c.text(`Internal server error: ${e instanceof Error ? e.message : 'Unknown error'}`, 500);
|
|
128
|
-
}
|
|
78
|
+
return handleMcpRequest(c, def, options, def.name);
|
|
129
79
|
});
|
|
130
80
|
}
|
|
131
81
|
|
|
132
82
|
return { serverDefs };
|
|
133
83
|
}
|
|
84
|
+
|
|
85
|
+
async function handleMcpRequest(c: any, def: McpServerHandlerDef, options: any, name: string) {
|
|
86
|
+
let item: McpServerInstance | undefined;
|
|
87
|
+
try {
|
|
88
|
+
item = def.create(options);
|
|
89
|
+
if (!item) return c.text(`Failed to create ${name} server`, 500);
|
|
90
|
+
} catch (e) {
|
|
91
|
+
log.error(`Failed to create ${name} server:`, e);
|
|
92
|
+
return c.text(`Failed to create ${name} server`, 500);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const transport = new StreamableHTTPTransport();
|
|
96
|
+
try {
|
|
97
|
+
await item.server.connect(transport);
|
|
98
|
+
const handleRequest = createMcpLoggingHandler(transport, name);
|
|
99
|
+
return await handleRequest(c);
|
|
100
|
+
} catch (e) {
|
|
101
|
+
log.error(`[${name}] Request error:`, e);
|
|
102
|
+
item.close?.().catch(() => {});
|
|
103
|
+
return c.text(`Internal server error: ${e instanceof Error ? e.message : 'Unknown error'}`, 500);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import { implement } from '@orpc/server';
|
|
2
2
|
import { McpsContract, type ModelInfo, type ServerInfo, type ServerTypeInfo, type ToolInfo } from '../contracts';
|
|
3
3
|
import { findMcpServerDef } from '../providers/findMcpServerDef';
|
|
4
|
-
import { getAuditStats, queryAuditEvents } from './audit';
|
|
5
4
|
import type { McpsConfig } from './schema';
|
|
5
|
+
import type { StatsProvider } from './server';
|
|
6
6
|
|
|
7
|
-
// Simple glob pattern matching
|
|
8
7
|
function matchGlob(pattern: string, text: string): boolean {
|
|
9
8
|
const regexPattern = pattern
|
|
10
|
-
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
9
|
+
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
11
10
|
.replace(/\*/g, '.*')
|
|
12
11
|
.replace(/\?/g, '.');
|
|
13
12
|
return new RegExp(`^${regexPattern}$`, 'i').test(text);
|
|
14
13
|
}
|
|
15
14
|
|
|
16
|
-
// Build server types from registry
|
|
17
15
|
function getServerTypes(): ServerTypeInfo[] {
|
|
18
16
|
return findMcpServerDef().map((def) => ({
|
|
19
17
|
type: def.name,
|
|
@@ -22,7 +20,6 @@ function getServerTypes(): ServerTypeInfo[] {
|
|
|
22
20
|
}));
|
|
23
21
|
}
|
|
24
22
|
|
|
25
|
-
// Build endpoints from server types
|
|
26
23
|
function getEndpoints(): string[] {
|
|
27
24
|
const mcpEndpoints = findMcpServerDef().map((def) => `/mcp/${def.name}`);
|
|
28
25
|
const chatEndpoints = [
|
|
@@ -38,22 +35,27 @@ function getEndpoints(): string[] {
|
|
|
38
35
|
|
|
39
36
|
export interface McpsRouterContext {
|
|
40
37
|
config: McpsConfig;
|
|
38
|
+
/** Optional stats provider (e.g. from audit plugin) */
|
|
39
|
+
statsProvider?: StatsProvider;
|
|
41
40
|
}
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
const emptyStats = {
|
|
43
|
+
totalRequests: 0,
|
|
44
|
+
totalErrors: 0,
|
|
45
|
+
avgDurationMs: 0,
|
|
46
|
+
byServer: [] as Array<{ name: string; count: number }>,
|
|
47
|
+
byMethod: [] as Array<{ method: string; count: number }>,
|
|
48
|
+
};
|
|
49
|
+
|
|
46
50
|
export function createMcpsRouter(ctx: McpsRouterContext) {
|
|
47
|
-
const { config } = ctx;
|
|
51
|
+
const { config, statsProvider } = ctx;
|
|
48
52
|
|
|
49
|
-
// Build server info list
|
|
50
53
|
const servers: ServerInfo[] = Object.entries(config.servers).map(([name, serverConfig]) => ({
|
|
51
54
|
name,
|
|
52
55
|
type: serverConfig.type,
|
|
53
56
|
disabled: serverConfig.disabled,
|
|
54
57
|
}));
|
|
55
58
|
|
|
56
|
-
// Build model info list
|
|
57
59
|
const models: ModelInfo[] = (config.models ?? []).map((model) => ({
|
|
58
60
|
name: model.name,
|
|
59
61
|
adapter: model.adapter,
|
|
@@ -76,10 +78,13 @@ export function createMcpsRouter(ctx: McpsRouterContext) {
|
|
|
76
78
|
}),
|
|
77
79
|
|
|
78
80
|
stats: implement(McpsContract.stats).handler(async ({ input }) => {
|
|
79
|
-
|
|
81
|
+
if (!statsProvider) {
|
|
82
|
+
return { ...emptyStats, byEndpoint: [] };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const auditStats = statsProvider.getStats(input);
|
|
86
|
+
const { events } = statsProvider.queryEvents({ limit: 10000 });
|
|
80
87
|
|
|
81
|
-
// Build endpoint stats from audit events
|
|
82
|
-
const { events } = queryAuditEvents({ limit: 10000 });
|
|
83
88
|
const endpointCounts = new Map<string, number>();
|
|
84
89
|
for (const event of events) {
|
|
85
90
|
const endpoint = event.path || 'unknown';
|
|
@@ -88,12 +93,9 @@ export function createMcpsRouter(ctx: McpsRouterContext) {
|
|
|
88
93
|
const byEndpoint = Array.from(endpointCounts.entries())
|
|
89
94
|
.map(([endpoint, count]) => ({ endpoint, count }))
|
|
90
95
|
.sort((a, b) => b.count - a.count)
|
|
91
|
-
.slice(0, 20);
|
|
96
|
+
.slice(0, 20);
|
|
92
97
|
|
|
93
|
-
return {
|
|
94
|
-
...auditStats,
|
|
95
|
-
byEndpoint,
|
|
96
|
-
};
|
|
98
|
+
return { ...auditStats, byEndpoint };
|
|
97
99
|
}),
|
|
98
100
|
|
|
99
101
|
servers: implement(McpsContract.servers).handler(async () => {
|
|
@@ -105,17 +107,7 @@ export function createMcpsRouter(ctx: McpsRouterContext) {
|
|
|
105
107
|
}),
|
|
106
108
|
|
|
107
109
|
tools: implement(McpsContract.tools).handler(async ({ input }) => {
|
|
108
|
-
// TODO: This is a placeholder that returns empty tools list.
|
|
109
|
-
// Full implementation would require connecting to each MCP server
|
|
110
|
-
// and calling tools/list. Consider caching tool lists and
|
|
111
|
-
// refreshing periodically or on demand.
|
|
112
110
|
const tools: ToolInfo[] = [];
|
|
113
|
-
|
|
114
|
-
// For now, return an empty list.
|
|
115
|
-
// When MCP servers support persistent connections or when we
|
|
116
|
-
// implement a tool registry, this will be populated.
|
|
117
|
-
|
|
118
|
-
// Apply filters if provided
|
|
119
111
|
let filteredTools = tools;
|
|
120
112
|
|
|
121
113
|
if (input.server) {
|
package/src/server/schema.ts
CHANGED
|
@@ -14,6 +14,9 @@ export const HeaderNames = {
|
|
|
14
14
|
MCP_URL: 'X-MCP-URL',
|
|
15
15
|
MCP_TYPE: 'X-MCP-TYPE',
|
|
16
16
|
MCP_COMMAND: 'X-MCP-COMMAND',
|
|
17
|
+
FEISHU_APP_ID: 'X-FEISHU-APP-ID',
|
|
18
|
+
FEISHU_APP_SECRET: 'X-FEISHU-APP-SECRET',
|
|
19
|
+
FEISHU_DOMAIN: 'X-FEISHU-DOMAIN',
|
|
17
20
|
// Tool filtering headers
|
|
18
21
|
MCP_READONLY: 'X-MCP-Readonly',
|
|
19
22
|
MCP_INCLUDE: 'X-MCP-Include',
|
|
@@ -53,6 +56,15 @@ export const PrometheusConfigSchema = BaseServerConfigSchema.extend({
|
|
|
53
56
|
});
|
|
54
57
|
export type PrometheusConfig = z.infer<typeof PrometheusConfigSchema>;
|
|
55
58
|
|
|
59
|
+
// Feishu/Lark config
|
|
60
|
+
export const FeishuConfigSchema = BaseServerConfigSchema.extend({
|
|
61
|
+
type: z.literal('feishu'),
|
|
62
|
+
appId: z.string().optional().describe('Feishu App ID'),
|
|
63
|
+
appSecret: z.string().optional().describe('Feishu App Secret'),
|
|
64
|
+
domain: z.string().optional().describe('feishu (China) or lark (International)'),
|
|
65
|
+
});
|
|
66
|
+
export type FeishuConfig = z.infer<typeof FeishuConfigSchema>;
|
|
67
|
+
|
|
56
68
|
// Relay config for proxying to other MCP servers
|
|
57
69
|
export const RelayConfigSchema = BaseServerConfigSchema.extend({
|
|
58
70
|
type: z.literal('relay'),
|
|
@@ -63,13 +75,22 @@ export const RelayConfigSchema = BaseServerConfigSchema.extend({
|
|
|
63
75
|
});
|
|
64
76
|
export type RelayConfig = z.infer<typeof RelayConfigSchema>;
|
|
65
77
|
|
|
66
|
-
//
|
|
67
|
-
|
|
78
|
+
// Known server config schemas
|
|
79
|
+
const KnownServerConfigSchema = z.discriminatedUnion('type', [
|
|
68
80
|
TencentClsConfigSchema,
|
|
69
81
|
SqlConfigSchema,
|
|
70
82
|
PrometheusConfigSchema,
|
|
83
|
+
FeishuConfigSchema,
|
|
71
84
|
RelayConfigSchema,
|
|
72
85
|
]);
|
|
86
|
+
|
|
87
|
+
// Catch-all for custom/extension server types (e.g. platform-admin, fusionops-admin)
|
|
88
|
+
const GenericServerConfigSchema = BaseServerConfigSchema.extend({
|
|
89
|
+
type: z.string(),
|
|
90
|
+
}).passthrough();
|
|
91
|
+
|
|
92
|
+
// Union of known types with generic fallback for extensibility
|
|
93
|
+
export const ServerConfigSchema = z.union([KnownServerConfigSchema, GenericServerConfigSchema]);
|
|
73
94
|
export type ServerConfig = z.infer<typeof ServerConfigSchema>;
|
|
74
95
|
|
|
75
96
|
/**
|