opalserve 0.1.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -115
- package/assets/logo.svg +51 -0
- package/dist/auth/api-keys.d.ts +7 -0
- package/dist/auth/api-keys.d.ts.map +1 -0
- package/dist/auth/api-keys.js +12 -0
- package/dist/auth/api-keys.js.map +1 -0
- package/dist/auth/index.d.ts +4 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +4 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/middleware.d.ts +11 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +46 -0
- package/dist/auth/middleware.js.map +1 -0
- package/dist/auth/passwords.d.ts +3 -0
- package/dist/auth/passwords.d.ts.map +1 -0
- package/dist/auth/passwords.js +33 -0
- package/dist/auth/passwords.js.map +1 -0
- package/dist/cli/commands/admin.d.ts +13 -0
- package/dist/cli/commands/admin.d.ts.map +1 -0
- package/dist/cli/commands/admin.js +261 -0
- package/dist/cli/commands/admin.js.map +1 -0
- package/dist/cli/commands/auth.d.ts +4 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +77 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/context.d.ts +5 -0
- package/dist/cli/commands/context.d.ts.map +1 -0
- package/dist/cli/commands/context.js +190 -0
- package/dist/cli/commands/context.js.map +1 -0
- package/dist/cli/commands/health.d.ts +4 -0
- package/dist/cli/commands/health.d.ts.map +1 -0
- package/dist/cli/commands/health.js +36 -0
- package/dist/cli/commands/health.js.map +1 -0
- package/dist/cli/commands/init.d.ts +2 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +81 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/server.d.ts +10 -0
- package/dist/cli/commands/server.d.ts.map +1 -0
- package/dist/cli/commands/server.js +108 -0
- package/dist/cli/commands/server.js.map +1 -0
- package/dist/cli/commands/start.d.ts +6 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +63 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/status.d.ts +2 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +21 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/sync.d.ts +2 -0
- package/dist/cli/commands/sync.d.ts.map +1 -0
- package/dist/cli/commands/sync.js +58 -0
- package/dist/cli/commands/sync.js.map +1 -0
- package/dist/cli/commands/tools.d.ts +8 -0
- package/dist/cli/commands/tools.d.ts.map +1 -0
- package/dist/cli/commands/tools.js +28 -0
- package/dist/cli/commands/tools.js.map +1 -0
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +156 -30
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/ui/banner.d.ts +8 -0
- package/dist/cli/ui/banner.d.ts.map +1 -0
- package/dist/cli/ui/banner.js +54 -0
- package/dist/cli/ui/banner.js.map +1 -0
- package/dist/cli/ui/prompts.d.ts +11 -0
- package/dist/cli/ui/prompts.d.ts.map +1 -0
- package/dist/cli/ui/prompts.js +74 -0
- package/dist/cli/ui/prompts.js.map +1 -0
- package/dist/cli/ui/table.d.ts +5 -0
- package/dist/cli/ui/table.d.ts.map +1 -0
- package/dist/cli/ui/table.js +103 -0
- package/dist/cli/ui/table.js.map +1 -0
- package/dist/config/credentials.d.ts +10 -0
- package/dist/config/credentials.d.ts.map +1 -0
- package/dist/config/credentials.js +33 -0
- package/dist/config/credentials.js.map +1 -0
- package/dist/config/defaults.d.ts +5 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +20 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/loader.d.ts +4 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +57 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +2 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +2 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/constants.d.ts +5 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +5 -0
- package/dist/constants.js.map +1 -0
- package/dist/context/chunker.d.ts +2 -0
- package/dist/context/chunker.d.ts.map +1 -0
- package/dist/context/chunker.js +81 -0
- package/dist/context/chunker.js.map +1 -0
- package/dist/context/index.d.ts +26 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +97 -0
- package/dist/context/index.js.map +1 -0
- package/dist/core/discovery.d.ts +17 -0
- package/dist/core/discovery.d.ts.map +1 -0
- package/dist/core/discovery.js +31 -0
- package/dist/core/discovery.js.map +1 -0
- package/dist/core/proxy.d.ts +14 -0
- package/dist/core/proxy.d.ts.map +1 -0
- package/dist/core/proxy.js +36 -0
- package/dist/core/proxy.js.map +1 -0
- package/dist/core/registry.d.ts +30 -31
- package/dist/core/registry.d.ts.map +1 -1
- package/dist/core/registry.js +92 -234
- package/dist/core/registry.js.map +1 -1
- package/dist/core/secrets.d.ts +4 -0
- package/dist/core/secrets.d.ts.map +1 -0
- package/dist/core/secrets.js +40 -0
- package/dist/core/secrets.js.map +1 -0
- package/dist/core/server-manager.d.ts +18 -0
- package/dist/core/server-manager.d.ts.map +1 -0
- package/dist/core/server-manager.js +120 -0
- package/dist/core/server-manager.js.map +1 -0
- package/dist/dashboard/assets/index-BNOtcUPs.js +257 -0
- package/dist/dashboard/assets/index-Duwp34GW.css +1 -0
- package/dist/dashboard/index.html +14 -0
- package/dist/index.d.ts +22 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -9
- package/dist/index.js.map +1 -1
- package/dist/integrations/github.d.ts +5 -0
- package/dist/integrations/github.d.ts.map +1 -0
- package/dist/integrations/github.js +63 -0
- package/dist/integrations/github.js.map +1 -0
- package/dist/integrations/slack.d.ts +21 -0
- package/dist/integrations/slack.d.ts.map +1 -0
- package/dist/integrations/slack.js +61 -0
- package/dist/integrations/slack.js.map +1 -0
- package/dist/monitoring/tracker.d.ts +31 -0
- package/dist/monitoring/tracker.d.ts.map +1 -0
- package/dist/monitoring/tracker.js +86 -0
- package/dist/monitoring/tracker.js.map +1 -0
- package/dist/server/app.d.ts +8 -0
- package/dist/server/app.d.ts.map +1 -0
- package/dist/server/app.js +81 -0
- package/dist/server/app.js.map +1 -0
- package/dist/server/mcp-gateway.d.ts +12 -0
- package/dist/server/mcp-gateway.d.ts.map +1 -0
- package/dist/server/mcp-gateway.js +91 -0
- package/dist/server/mcp-gateway.js.map +1 -0
- package/dist/server/routes/auth.d.ts +4 -0
- package/dist/server/routes/auth.d.ts.map +1 -0
- package/dist/server/routes/auth.js +117 -0
- package/dist/server/routes/auth.js.map +1 -0
- package/dist/server/routes/context.d.ts +4 -0
- package/dist/server/routes/context.d.ts.map +1 -0
- package/dist/server/routes/context.js +107 -0
- package/dist/server/routes/context.js.map +1 -0
- package/dist/server/routes/health.d.ts +4 -0
- package/dist/server/routes/health.d.ts.map +1 -0
- package/dist/server/routes/health.js +22 -0
- package/dist/server/routes/health.js.map +1 -0
- package/dist/server/routes/servers.d.ts +4 -0
- package/dist/server/routes/servers.d.ts.map +1 -0
- package/dist/server/routes/servers.js +47 -0
- package/dist/server/routes/servers.js.map +1 -0
- package/dist/server/routes/stats.d.ts +4 -0
- package/dist/server/routes/stats.d.ts.map +1 -0
- package/dist/server/routes/stats.js +97 -0
- package/dist/server/routes/stats.js.map +1 -0
- package/dist/server/routes/team-servers.d.ts +4 -0
- package/dist/server/routes/team-servers.d.ts.map +1 -0
- package/dist/server/routes/team-servers.js +108 -0
- package/dist/server/routes/team-servers.js.map +1 -0
- package/dist/server/routes/tools.d.ts +4 -0
- package/dist/server/routes/tools.d.ts.map +1 -0
- package/dist/server/routes/tools.js +44 -0
- package/dist/server/routes/tools.js.map +1 -0
- package/dist/server/routes/webhooks.d.ts +4 -0
- package/dist/server/routes/webhooks.d.ts.map +1 -0
- package/dist/server/routes/webhooks.js +77 -0
- package/dist/server/routes/webhooks.js.map +1 -0
- package/dist/storage/database.d.ts +48 -0
- package/dist/storage/database.d.ts.map +1 -0
- package/dist/storage/database.js +336 -0
- package/dist/storage/database.js.map +1 -0
- package/dist/storage/repositories/server-repo.d.ts +2 -0
- package/dist/storage/repositories/server-repo.d.ts.map +1 -0
- package/dist/storage/repositories/server-repo.js +3 -0
- package/dist/storage/repositories/server-repo.js.map +1 -0
- package/dist/storage/repositories/tool-repo.d.ts +2 -0
- package/dist/storage/repositories/tool-repo.d.ts.map +1 -0
- package/dist/storage/repositories/tool-repo.js +3 -0
- package/dist/storage/repositories/tool-repo.js.map +1 -0
- package/dist/types/index.d.ts +482 -587
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +52 -69
- package/dist/types/index.js.map +1 -1
- package/dist/utils/logger.d.ts +7 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +23 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +67 -56
- package/.env.example +0 -19
- package/config/servers.example.yaml +0 -67
- package/config/servers.yaml +0 -2
- package/dist/cli/discover.d.ts +0 -3
- package/dist/cli/discover.d.ts.map +0 -1
- package/dist/cli/discover.js +0 -160
- package/dist/cli/discover.js.map +0 -1
- package/dist/connectors/base.d.ts +0 -49
- package/dist/connectors/base.d.ts.map +0 -1
- package/dist/connectors/base.js +0 -45
- package/dist/connectors/base.js.map +0 -1
- package/dist/connectors/custom.d.ts +0 -19
- package/dist/connectors/custom.d.ts.map +0 -1
- package/dist/connectors/custom.js +0 -129
- package/dist/connectors/custom.js.map +0 -1
- package/dist/connectors/github.d.ts +0 -18
- package/dist/connectors/github.d.ts.map +0 -1
- package/dist/connectors/github.js +0 -188
- package/dist/connectors/github.js.map +0 -1
- package/dist/connectors/google-drive.d.ts +0 -18
- package/dist/connectors/google-drive.d.ts.map +0 -1
- package/dist/connectors/google-drive.js +0 -209
- package/dist/connectors/google-drive.js.map +0 -1
- package/dist/connectors/index.d.ts +0 -11
- package/dist/connectors/index.d.ts.map +0 -1
- package/dist/connectors/index.js +0 -76
- package/dist/connectors/index.js.map +0 -1
- package/dist/connectors/postgres.d.ts +0 -18
- package/dist/connectors/postgres.d.ts.map +0 -1
- package/dist/connectors/postgres.js +0 -140
- package/dist/connectors/postgres.js.map +0 -1
- package/dist/connectors/slack.d.ts +0 -18
- package/dist/connectors/slack.d.ts.map +0 -1
- package/dist/connectors/slack.js +0 -181
- package/dist/connectors/slack.js.map +0 -1
- package/dist/core/auth.d.ts +0 -26
- package/dist/core/auth.d.ts.map +0 -1
- package/dist/core/auth.js +0 -81
- package/dist/core/auth.js.map +0 -1
- package/dist/core/tokenizer.d.ts +0 -16
- package/dist/core/tokenizer.d.ts.map +0 -1
- package/dist/core/tokenizer.js +0 -29
- package/dist/core/tokenizer.js.map +0 -1
- package/dist/governance/audit.d.ts +0 -27
- package/dist/governance/audit.d.ts.map +0 -1
- package/dist/governance/audit.js +0 -149
- package/dist/governance/audit.js.map +0 -1
- package/dist/governance/index.d.ts +0 -5
- package/dist/governance/index.d.ts.map +0 -1
- package/dist/governance/index.js +0 -5
- package/dist/governance/index.js.map +0 -1
- package/dist/governance/policy.d.ts +0 -20
- package/dist/governance/policy.d.ts.map +0 -1
- package/dist/governance/policy.js +0 -162
- package/dist/governance/policy.js.map +0 -1
- package/dist/governance/rate-limiter.d.ts +0 -20
- package/dist/governance/rate-limiter.d.ts.map +0 -1
- package/dist/governance/rate-limiter.js +0 -73
- package/dist/governance/rate-limiter.js.map +0 -1
- package/dist/governance/types.d.ts +0 -246
- package/dist/governance/types.d.ts.map +0 -1
- package/dist/governance/types.js +0 -72
- package/dist/governance/types.js.map +0 -1
- package/dist/identity/access-control.d.ts +0 -15
- package/dist/identity/access-control.d.ts.map +0 -1
- package/dist/identity/access-control.js +0 -81
- package/dist/identity/access-control.js.map +0 -1
- package/dist/identity/index.d.ts +0 -4
- package/dist/identity/index.d.ts.map +0 -1
- package/dist/identity/index.js +0 -4
- package/dist/identity/index.js.map +0 -1
- package/dist/identity/manager.d.ts +0 -29
- package/dist/identity/manager.d.ts.map +0 -1
- package/dist/identity/manager.js +0 -167
- package/dist/identity/manager.js.map +0 -1
- package/dist/identity/types.d.ts +0 -237
- package/dist/identity/types.d.ts.map +0 -1
- package/dist/identity/types.js +0 -80
- package/dist/identity/types.js.map +0 -1
- package/dist/registry/server.d.ts +0 -14
- package/dist/registry/server.d.ts.map +0 -1
- package/dist/registry/server.js +0 -177
- package/dist/registry/server.js.map +0 -1
- package/dist/utils/config.d.ts +0 -29
- package/dist/utils/config.d.ts.map +0 -1
- package/dist/utils/config.js +0 -47
- package/dist/utils/config.js.map +0 -1
- package/dist/utils/index.d.ts +0 -7
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -44
- package/dist/utils/index.js.map +0 -1
- package/dist/workflow/engine.d.ts +0 -18
- package/dist/workflow/engine.d.ts.map +0 -1
- package/dist/workflow/engine.js +0 -155
- package/dist/workflow/engine.js.map +0 -1
- package/dist/workflow/index.d.ts +0 -4
- package/dist/workflow/index.d.ts.map +0 -1
- package/dist/workflow/index.js +0 -4
- package/dist/workflow/index.js.map +0 -1
- package/dist/workflow/templates.d.ts +0 -4
- package/dist/workflow/templates.d.ts.map +0 -1
- package/dist/workflow/templates.js +0 -218
- package/dist/workflow/templates.js.map +0 -1
- package/dist/workflow/types.d.ts +0 -255
- package/dist/workflow/types.d.ts.map +0 -1
- package/dist/workflow/types.js +0 -48
- package/dist/workflow/types.js.map +0 -1
- package/eslint.config.js +0 -25
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { McpServerConfigSchema } from '../../types/index.js';
|
|
3
|
+
import { createAuthMiddleware } from '../../auth/middleware.js';
|
|
4
|
+
export function registerTeamServerRoutes(app, registry) {
|
|
5
|
+
const db = registry.getDatabase();
|
|
6
|
+
const requireAuth = createAuthMiddleware(db);
|
|
7
|
+
// --- List Team Servers ---
|
|
8
|
+
app.get('/api/v1/team/servers', { preHandler: requireAuth }, async (request, reply) => {
|
|
9
|
+
if (!request.user) {
|
|
10
|
+
return reply.status(401).send({ ok: false, error: 'Not authenticated' });
|
|
11
|
+
}
|
|
12
|
+
// Find user's team
|
|
13
|
+
const membership = db.get('SELECT team_id, role FROM team_members WHERE user_id = ?', [request.user.id]);
|
|
14
|
+
if (!membership) {
|
|
15
|
+
return reply.send({ ok: true, data: [] });
|
|
16
|
+
}
|
|
17
|
+
const servers = db.all('SELECT id, name, config_json, enabled, created_by, created_at, updated_at FROM team_servers WHERE team_id = ? ORDER BY name', [membership.team_id]);
|
|
18
|
+
const data = servers.map(s => ({
|
|
19
|
+
id: s.id,
|
|
20
|
+
name: s.name,
|
|
21
|
+
config: JSON.parse(s.config_json),
|
|
22
|
+
enabled: s.enabled === 1,
|
|
23
|
+
createdBy: s.created_by,
|
|
24
|
+
createdAt: s.created_at,
|
|
25
|
+
updatedAt: s.updated_at,
|
|
26
|
+
}));
|
|
27
|
+
return reply.send({ ok: true, data });
|
|
28
|
+
});
|
|
29
|
+
// --- Add Team Server (admin only) ---
|
|
30
|
+
app.post('/api/v1/team/servers', { preHandler: requireAuth }, async (request, reply) => {
|
|
31
|
+
if (!request.user) {
|
|
32
|
+
return reply.status(401).send({ ok: false, error: 'Not authenticated' });
|
|
33
|
+
}
|
|
34
|
+
const membership = db.get('SELECT team_id, role FROM team_members WHERE user_id = ?', [request.user.id]);
|
|
35
|
+
if (!membership || membership.role !== 'admin') {
|
|
36
|
+
return reply.status(403).send({ ok: false, error: 'Admin access required' });
|
|
37
|
+
}
|
|
38
|
+
const parsed = McpServerConfigSchema.safeParse(request.body);
|
|
39
|
+
if (!parsed.success) {
|
|
40
|
+
return reply.status(400).send({
|
|
41
|
+
ok: false,
|
|
42
|
+
error: 'Invalid server configuration',
|
|
43
|
+
details: parsed.error.flatten(),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
const now = new Date().toISOString();
|
|
47
|
+
const id = randomUUID();
|
|
48
|
+
try {
|
|
49
|
+
db.run('INSERT INTO team_servers (id, team_id, name, config_json, created_by, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)', [id, membership.team_id, parsed.data.name, JSON.stringify(parsed.data), request.user.id, now, now]);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
53
|
+
if (message.includes('UNIQUE')) {
|
|
54
|
+
return reply.status(409).send({ ok: false, error: `Server "${parsed.data.name}" already exists in this team` });
|
|
55
|
+
}
|
|
56
|
+
return reply.status(500).send({ ok: false, error: message });
|
|
57
|
+
}
|
|
58
|
+
return reply.status(201).send({
|
|
59
|
+
ok: true,
|
|
60
|
+
data: {
|
|
61
|
+
id,
|
|
62
|
+
name: parsed.data.name,
|
|
63
|
+
config: parsed.data,
|
|
64
|
+
enabled: true,
|
|
65
|
+
createdBy: request.user.id,
|
|
66
|
+
createdAt: now,
|
|
67
|
+
updatedAt: now,
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
// --- Remove Team Server (admin only) ---
|
|
72
|
+
app.delete('/api/v1/team/servers/:name', { preHandler: requireAuth }, async (request, reply) => {
|
|
73
|
+
if (!request.user) {
|
|
74
|
+
return reply.status(401).send({ ok: false, error: 'Not authenticated' });
|
|
75
|
+
}
|
|
76
|
+
const membership = db.get('SELECT team_id, role FROM team_members WHERE user_id = ?', [request.user.id]);
|
|
77
|
+
if (!membership || membership.role !== 'admin') {
|
|
78
|
+
return reply.status(403).send({ ok: false, error: 'Admin access required' });
|
|
79
|
+
}
|
|
80
|
+
const { name } = request.params;
|
|
81
|
+
const existing = db.get('SELECT id FROM team_servers WHERE team_id = ? AND name = ?', [membership.team_id, name]);
|
|
82
|
+
if (!existing) {
|
|
83
|
+
return reply.status(404).send({ ok: false, error: `Server "${name}" not found` });
|
|
84
|
+
}
|
|
85
|
+
db.run('DELETE FROM team_servers WHERE team_id = ? AND name = ?', [membership.team_id, name]);
|
|
86
|
+
return reply.send({ ok: true });
|
|
87
|
+
});
|
|
88
|
+
// --- Sync Team Servers ---
|
|
89
|
+
app.get('/api/v1/team/servers/sync', { preHandler: requireAuth }, async (request, reply) => {
|
|
90
|
+
if (!request.user) {
|
|
91
|
+
return reply.status(401).send({ ok: false, error: 'Not authenticated' });
|
|
92
|
+
}
|
|
93
|
+
const membership = db.get('SELECT team_id, role FROM team_members WHERE user_id = ?', [request.user.id]);
|
|
94
|
+
if (!membership) {
|
|
95
|
+
return reply.send({ ok: true, data: { servers: [], teamId: null } });
|
|
96
|
+
}
|
|
97
|
+
const servers = db.all('SELECT name, config_json, enabled FROM team_servers WHERE team_id = ? AND enabled = 1 ORDER BY name', [membership.team_id]);
|
|
98
|
+
const configs = servers.map(s => JSON.parse(s.config_json));
|
|
99
|
+
return reply.send({
|
|
100
|
+
ok: true,
|
|
101
|
+
data: {
|
|
102
|
+
teamId: membership.team_id,
|
|
103
|
+
servers: configs,
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=team-servers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team-servers.js","sourceRoot":"","sources":["../../../src/server/routes/team-servers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../../src/server/routes/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,eAAe,EAAE,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAkD1F"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export function registerToolRoutes(app, registry) {
|
|
2
|
+
app.get('/api/v1/tools', async (request, reply) => {
|
|
3
|
+
const { server } = request.query;
|
|
4
|
+
const serverFilter = server ? server.split(',') : undefined;
|
|
5
|
+
const tools = registry.listTools(serverFilter);
|
|
6
|
+
return reply.send({ ok: true, data: tools });
|
|
7
|
+
});
|
|
8
|
+
app.get('/api/v1/tools/search', async (request, reply) => {
|
|
9
|
+
const { q, limit, server } = request.query;
|
|
10
|
+
if (!q) {
|
|
11
|
+
return reply.status(400).send({ ok: false, error: 'Query parameter "q" is required' });
|
|
12
|
+
}
|
|
13
|
+
const serverFilter = server ? server.split(',') : undefined;
|
|
14
|
+
const results = registry.searchTools(q, {
|
|
15
|
+
limit: limit ? parseInt(limit, 10) : undefined,
|
|
16
|
+
serverFilter,
|
|
17
|
+
});
|
|
18
|
+
return reply.send({ ok: true, data: results });
|
|
19
|
+
});
|
|
20
|
+
app.get('/api/v1/tools/:id', async (request, reply) => {
|
|
21
|
+
const { id } = request.params;
|
|
22
|
+
// Tool IDs contain colons, so decode the URL param
|
|
23
|
+
const toolId = decodeURIComponent(id);
|
|
24
|
+
const tool = registry.discovery.getById(toolId);
|
|
25
|
+
if (!tool) {
|
|
26
|
+
return reply.status(404).send({ ok: false, error: `Tool "${toolId}" not found` });
|
|
27
|
+
}
|
|
28
|
+
return reply.send({ ok: true, data: tool });
|
|
29
|
+
});
|
|
30
|
+
app.post('/api/v1/tools/:id/call', async (request, reply) => {
|
|
31
|
+
const { id } = request.params;
|
|
32
|
+
const toolId = decodeURIComponent(id);
|
|
33
|
+
const args = request.body || {};
|
|
34
|
+
try {
|
|
35
|
+
const result = await registry.callTool(toolId, args);
|
|
36
|
+
return reply.send({ ok: true, data: result });
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
40
|
+
return reply.status(500).send({ ok: false, error: message });
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../src/server/routes/tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../../src/server/routes/webhooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAKhE,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,eAAe,EAAE,SAAS,EAAE,iBAAiB,GAAG,IAAI,CA6D9F"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { createLogger } from '../../utils/logger.js';
|
|
2
|
+
const log = createLogger('webhooks');
|
|
3
|
+
export function registerWebhookRoutes(app, _registry) {
|
|
4
|
+
// --- GitHub Webhook ---
|
|
5
|
+
app.post('/api/v1/webhooks/github', async (request, reply) => {
|
|
6
|
+
const event = request.headers['x-github-event'];
|
|
7
|
+
const delivery = request.headers['x-github-delivery'];
|
|
8
|
+
log.info({ event, delivery }, 'Received GitHub webhook');
|
|
9
|
+
try {
|
|
10
|
+
await handleGitHubWebhook(event ?? 'unknown', request.body);
|
|
11
|
+
return reply.send({ ok: true });
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
15
|
+
log.error({ error: message }, 'GitHub webhook error');
|
|
16
|
+
return reply.status(500).send({ ok: false, error: message });
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
// --- Slack Event Subscription ---
|
|
20
|
+
app.post('/api/v1/slack/events', async (request, reply) => {
|
|
21
|
+
const body = request.body;
|
|
22
|
+
// Slack URL verification challenge
|
|
23
|
+
if (body.type === 'url_verification') {
|
|
24
|
+
return reply.send({ challenge: body.challenge });
|
|
25
|
+
}
|
|
26
|
+
log.info({ type: body.type }, 'Received Slack event');
|
|
27
|
+
try {
|
|
28
|
+
await handleSlackEvent(body);
|
|
29
|
+
return reply.send({ ok: true });
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
33
|
+
log.error({ error: message }, 'Slack event error');
|
|
34
|
+
return reply.status(500).send({ ok: false, error: message });
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
// --- Slack Slash Command ---
|
|
38
|
+
app.post('/api/v1/slack/commands', async (request, reply) => {
|
|
39
|
+
const body = request.body;
|
|
40
|
+
const command = body.command;
|
|
41
|
+
const text = body.text;
|
|
42
|
+
const userId = body.user_id;
|
|
43
|
+
log.info({ command, text, userId }, 'Received Slack slash command');
|
|
44
|
+
try {
|
|
45
|
+
const response = await handleSlackCommand(command ?? '', text ?? '', userId ?? '');
|
|
46
|
+
return reply.send(response);
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
50
|
+
log.error({ error: message }, 'Slack command error');
|
|
51
|
+
return reply.send({
|
|
52
|
+
response_type: 'ephemeral',
|
|
53
|
+
text: `Error: ${message}`,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
async function handleGitHubWebhook(event, payload) {
|
|
59
|
+
log.debug({ event, action: payload.action }, 'Processing GitHub webhook');
|
|
60
|
+
// Extensible: consumers can add handlers for specific events
|
|
61
|
+
// e.g., push, pull_request, issues, etc.
|
|
62
|
+
}
|
|
63
|
+
async function handleSlackEvent(payload) {
|
|
64
|
+
const event = payload.event;
|
|
65
|
+
log.debug({ eventType: event?.type }, 'Processing Slack event');
|
|
66
|
+
// Extensible: consumers can add handlers for specific event types
|
|
67
|
+
// e.g., message, app_mention, reaction_added, etc.
|
|
68
|
+
}
|
|
69
|
+
async function handleSlackCommand(command, text, _userId) {
|
|
70
|
+
log.debug({ command, text }, 'Processing Slack command');
|
|
71
|
+
// Default response for unhandled commands
|
|
72
|
+
return {
|
|
73
|
+
response_type: 'ephemeral',
|
|
74
|
+
text: `Received command: ${command} ${text}`,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=webhooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../../src/server/routes/webhooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Database as SqlJsDatabase } from 'sql.js';
|
|
2
|
+
import type { McpServerConfig, ConnectedServer, ServerStatus, IndexedTool, ToolAnnotations } from '../types/index.js';
|
|
3
|
+
export declare class Database {
|
|
4
|
+
private db;
|
|
5
|
+
private filePath;
|
|
6
|
+
private constructor();
|
|
7
|
+
static open(filePath?: string): Promise<Database>;
|
|
8
|
+
static inMemory(): Promise<Database>;
|
|
9
|
+
save(): void;
|
|
10
|
+
close(): void;
|
|
11
|
+
run(sql: string, params?: unknown[]): void;
|
|
12
|
+
get<T = Record<string, unknown>>(sql: string, params?: unknown[]): T | null;
|
|
13
|
+
all<T = Record<string, unknown>>(sql: string, params?: unknown[]): T[];
|
|
14
|
+
upsertServer(config: McpServerConfig): void;
|
|
15
|
+
getServer(name: string): {
|
|
16
|
+
config: McpServerConfig;
|
|
17
|
+
server: ConnectedServer;
|
|
18
|
+
} | null;
|
|
19
|
+
getAllServers(): {
|
|
20
|
+
config: McpServerConfig;
|
|
21
|
+
server: ConnectedServer;
|
|
22
|
+
}[];
|
|
23
|
+
removeServer(name: string): boolean;
|
|
24
|
+
updateServerStatus(name: string, status: ServerStatus, error?: string | null): void;
|
|
25
|
+
updateServerInfo(name: string, info: {
|
|
26
|
+
name: string;
|
|
27
|
+
version: string;
|
|
28
|
+
}, toolCount: number): void;
|
|
29
|
+
upsertTools(serverName: string, tools: {
|
|
30
|
+
name: string;
|
|
31
|
+
description?: string;
|
|
32
|
+
inputSchema?: unknown;
|
|
33
|
+
annotations?: ToolAnnotations;
|
|
34
|
+
}[]): void;
|
|
35
|
+
getTool(id: string): IndexedTool | null;
|
|
36
|
+
getToolsByServer(serverName: string): IndexedTool[];
|
|
37
|
+
getAllTools(): IndexedTool[];
|
|
38
|
+
searchTools(query: string, limit?: number): {
|
|
39
|
+
tool: IndexedTool;
|
|
40
|
+
score: number;
|
|
41
|
+
}[];
|
|
42
|
+
removeToolsByServer(serverName: string): void;
|
|
43
|
+
toolCount(): number;
|
|
44
|
+
private toServerResult;
|
|
45
|
+
private toTool;
|
|
46
|
+
getRawDb(): SqlJsDatabase;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=database.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/storage/database.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,IAAI,aAAa,EAAE,MAAM,QAAQ,CAAC;AAKxD,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAkJtH,qBAAa,QAAQ;IACnB,OAAO,CAAC,EAAE,CAAgB;IAC1B,OAAO,CAAC,QAAQ,CAAgB;IAEhC,OAAO;WAKM,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;WAsB1C,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;IAQ1C,IAAI,IAAI,IAAI;IAOZ,KAAK,IAAI,IAAI;IAKb,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI;IAK1C,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,GAAG,IAAI;IAY3E,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE;IAatE,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IAS3C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,MAAM,EAAE,eAAe,CAAC;QAAC,MAAM,EAAE,eAAe,CAAA;KAAE,GAAG,IAAI;IAMpF,aAAa,IAAI;QAAE,MAAM,EAAE,eAAe,CAAC;QAAC,MAAM,EAAE,eAAe,CAAA;KAAE,EAAE;IAKvE,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAMnC,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAKnF,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAOhG,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,eAAe,CAAA;KAAE,EAAE,GAAG,IAAI;IAY5I,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAKvC,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,WAAW,EAAE;IAKnD,WAAW,IAAI,WAAW,EAAE;IAK5B,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG;QAAE,IAAI,EAAE,WAAW,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE;IAuB9E,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAI7C,SAAS,IAAI,MAAM;IAOnB,OAAO,CAAC,cAAc;IAiBtB,OAAO,CAAC,MAAM;IAad,QAAQ,IAAI,aAAa;CAG1B"}
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import initSqlJs from 'sql.js';
|
|
2
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { getDefaultDbPath } from '../config/defaults.js';
|
|
6
|
+
let SQL = null;
|
|
7
|
+
async function getSqlJs() {
|
|
8
|
+
if (!SQL) {
|
|
9
|
+
// Try to find the wasm file
|
|
10
|
+
let wasmBinary;
|
|
11
|
+
try {
|
|
12
|
+
const sqlJsPath = dirname(fileURLToPath(import.meta.resolve('sql.js')));
|
|
13
|
+
const wasmPath = join(sqlJsPath, 'dist', 'sql-wasm.wasm');
|
|
14
|
+
if (existsSync(wasmPath)) {
|
|
15
|
+
wasmBinary = readFileSync(wasmPath);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// Let sql.js find it on its own
|
|
20
|
+
}
|
|
21
|
+
SQL = await initSqlJs(wasmBinary ? { wasmBinary } : undefined);
|
|
22
|
+
}
|
|
23
|
+
return SQL;
|
|
24
|
+
}
|
|
25
|
+
const SCHEMA = `
|
|
26
|
+
CREATE TABLE IF NOT EXISTS servers (
|
|
27
|
+
name TEXT PRIMARY KEY,
|
|
28
|
+
config_json TEXT NOT NULL,
|
|
29
|
+
status TEXT NOT NULL DEFAULT 'disconnected',
|
|
30
|
+
server_info TEXT,
|
|
31
|
+
tool_count INTEGER DEFAULT 0,
|
|
32
|
+
last_seen TEXT,
|
|
33
|
+
error TEXT,
|
|
34
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
35
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
CREATE TABLE IF NOT EXISTS tools (
|
|
39
|
+
id TEXT PRIMARY KEY,
|
|
40
|
+
server_name TEXT NOT NULL,
|
|
41
|
+
name TEXT NOT NULL,
|
|
42
|
+
description TEXT DEFAULT '',
|
|
43
|
+
input_schema TEXT,
|
|
44
|
+
annotations TEXT,
|
|
45
|
+
discovered_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
46
|
+
last_verified TEXT NOT NULL DEFAULT (datetime('now'))
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
CREATE INDEX IF NOT EXISTS idx_tools_server ON tools(server_name);
|
|
50
|
+
CREATE INDEX IF NOT EXISTS idx_tools_name ON tools(name);
|
|
51
|
+
|
|
52
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
53
|
+
id TEXT PRIMARY KEY,
|
|
54
|
+
email TEXT UNIQUE NOT NULL,
|
|
55
|
+
password_hash TEXT NOT NULL,
|
|
56
|
+
display_name TEXT,
|
|
57
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
58
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
CREATE TABLE IF NOT EXISTS teams (
|
|
62
|
+
id TEXT PRIMARY KEY,
|
|
63
|
+
name TEXT NOT NULL,
|
|
64
|
+
slug TEXT UNIQUE NOT NULL,
|
|
65
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
CREATE TABLE IF NOT EXISTS team_members (
|
|
69
|
+
team_id TEXT NOT NULL,
|
|
70
|
+
user_id TEXT NOT NULL,
|
|
71
|
+
role TEXT NOT NULL DEFAULT 'member',
|
|
72
|
+
joined_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
73
|
+
PRIMARY KEY (team_id, user_id)
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
CREATE TABLE IF NOT EXISTS api_keys (
|
|
77
|
+
id TEXT PRIMARY KEY,
|
|
78
|
+
user_id TEXT NOT NULL,
|
|
79
|
+
key_hash TEXT NOT NULL,
|
|
80
|
+
key_prefix TEXT NOT NULL,
|
|
81
|
+
name TEXT NOT NULL,
|
|
82
|
+
last_used_at TEXT,
|
|
83
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
84
|
+
expires_at TEXT
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
CREATE TABLE IF NOT EXISTS team_servers (
|
|
88
|
+
id TEXT PRIMARY KEY,
|
|
89
|
+
team_id TEXT NOT NULL,
|
|
90
|
+
name TEXT NOT NULL,
|
|
91
|
+
config_json TEXT NOT NULL,
|
|
92
|
+
credentials_encrypted TEXT,
|
|
93
|
+
enabled INTEGER DEFAULT 1,
|
|
94
|
+
created_by TEXT,
|
|
95
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
96
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
97
|
+
UNIQUE(team_id, name)
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
CREATE TABLE IF NOT EXISTS context_documents (
|
|
101
|
+
id TEXT PRIMARY KEY,
|
|
102
|
+
team_id TEXT,
|
|
103
|
+
title TEXT NOT NULL,
|
|
104
|
+
content TEXT NOT NULL,
|
|
105
|
+
content_type TEXT DEFAULT 'text/markdown',
|
|
106
|
+
source TEXT,
|
|
107
|
+
tags TEXT DEFAULT '[]',
|
|
108
|
+
uploaded_by TEXT,
|
|
109
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
110
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
CREATE TABLE IF NOT EXISTS usage_events (
|
|
114
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
115
|
+
team_id TEXT,
|
|
116
|
+
user_id TEXT,
|
|
117
|
+
event_type TEXT NOT NULL,
|
|
118
|
+
server_name TEXT,
|
|
119
|
+
tool_name TEXT,
|
|
120
|
+
latency_ms INTEGER,
|
|
121
|
+
success INTEGER,
|
|
122
|
+
error TEXT,
|
|
123
|
+
metadata TEXT,
|
|
124
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
CREATE INDEX IF NOT EXISTS idx_usage_user ON usage_events(user_id, created_at);
|
|
128
|
+
CREATE INDEX IF NOT EXISTS idx_usage_team ON usage_events(team_id, created_at);
|
|
129
|
+
|
|
130
|
+
CREATE TABLE IF NOT EXISTS rate_limits (
|
|
131
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
132
|
+
team_id TEXT NOT NULL,
|
|
133
|
+
user_id TEXT,
|
|
134
|
+
role TEXT,
|
|
135
|
+
limit_type TEXT NOT NULL,
|
|
136
|
+
max_value INTEGER NOT NULL
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
CREATE TABLE IF NOT EXISTS tool_permissions (
|
|
140
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
141
|
+
team_id TEXT NOT NULL,
|
|
142
|
+
role TEXT NOT NULL,
|
|
143
|
+
server_name TEXT NOT NULL,
|
|
144
|
+
tool_name TEXT,
|
|
145
|
+
permission TEXT NOT NULL DEFAULT 'allow'
|
|
146
|
+
);
|
|
147
|
+
`;
|
|
148
|
+
export class Database {
|
|
149
|
+
db;
|
|
150
|
+
filePath;
|
|
151
|
+
constructor(db, filePath) {
|
|
152
|
+
this.db = db;
|
|
153
|
+
this.filePath = filePath;
|
|
154
|
+
}
|
|
155
|
+
static async open(filePath) {
|
|
156
|
+
const resolved = filePath || getDefaultDbPath();
|
|
157
|
+
mkdirSync(dirname(resolved), { recursive: true });
|
|
158
|
+
const SqlJs = await getSqlJs();
|
|
159
|
+
let db;
|
|
160
|
+
if (existsSync(resolved)) {
|
|
161
|
+
const buffer = readFileSync(resolved);
|
|
162
|
+
db = new SqlJs.Database(buffer);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
db = new SqlJs.Database();
|
|
166
|
+
}
|
|
167
|
+
db.run('PRAGMA foreign_keys = ON');
|
|
168
|
+
db.run(SCHEMA);
|
|
169
|
+
const instance = new Database(db, resolved);
|
|
170
|
+
instance.save();
|
|
171
|
+
return instance;
|
|
172
|
+
}
|
|
173
|
+
static async inMemory() {
|
|
174
|
+
const SqlJs = await getSqlJs();
|
|
175
|
+
const db = new SqlJs.Database();
|
|
176
|
+
db.run('PRAGMA foreign_keys = ON');
|
|
177
|
+
db.run(SCHEMA);
|
|
178
|
+
return new Database(db, null);
|
|
179
|
+
}
|
|
180
|
+
save() {
|
|
181
|
+
if (this.filePath) {
|
|
182
|
+
const data = this.db.export();
|
|
183
|
+
writeFileSync(this.filePath, Buffer.from(data));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
close() {
|
|
187
|
+
this.save();
|
|
188
|
+
this.db.close();
|
|
189
|
+
}
|
|
190
|
+
run(sql, params) {
|
|
191
|
+
this.db.run(sql, params);
|
|
192
|
+
this.save();
|
|
193
|
+
}
|
|
194
|
+
get(sql, params) {
|
|
195
|
+
const stmt = this.db.prepare(sql);
|
|
196
|
+
if (params)
|
|
197
|
+
stmt.bind(params);
|
|
198
|
+
if (stmt.step()) {
|
|
199
|
+
const row = stmt.getAsObject();
|
|
200
|
+
stmt.free();
|
|
201
|
+
return row;
|
|
202
|
+
}
|
|
203
|
+
stmt.free();
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
all(sql, params) {
|
|
207
|
+
const results = [];
|
|
208
|
+
const stmt = this.db.prepare(sql);
|
|
209
|
+
if (params)
|
|
210
|
+
stmt.bind(params);
|
|
211
|
+
while (stmt.step()) {
|
|
212
|
+
results.push(stmt.getAsObject());
|
|
213
|
+
}
|
|
214
|
+
stmt.free();
|
|
215
|
+
return results;
|
|
216
|
+
}
|
|
217
|
+
// --- Server Operations ---
|
|
218
|
+
upsertServer(config) {
|
|
219
|
+
const now = new Date().toISOString();
|
|
220
|
+
this.run(`
|
|
221
|
+
INSERT INTO servers (name, config_json, status, created_at, updated_at)
|
|
222
|
+
VALUES (?, ?, 'disconnected', ?, ?)
|
|
223
|
+
ON CONFLICT(name) DO UPDATE SET config_json = excluded.config_json, updated_at = ?
|
|
224
|
+
`, [config.name, JSON.stringify(config), now, now, now]);
|
|
225
|
+
}
|
|
226
|
+
getServer(name) {
|
|
227
|
+
const row = this.get('SELECT * FROM servers WHERE name = ?', [name]);
|
|
228
|
+
if (!row)
|
|
229
|
+
return null;
|
|
230
|
+
return this.toServerResult(row);
|
|
231
|
+
}
|
|
232
|
+
getAllServers() {
|
|
233
|
+
const rows = this.all('SELECT * FROM servers ORDER BY name');
|
|
234
|
+
return rows.map(r => this.toServerResult(r));
|
|
235
|
+
}
|
|
236
|
+
removeServer(name) {
|
|
237
|
+
this.run('DELETE FROM tools WHERE server_name = ?', [name]);
|
|
238
|
+
this.run('DELETE FROM servers WHERE name = ?', [name]);
|
|
239
|
+
return true;
|
|
240
|
+
}
|
|
241
|
+
updateServerStatus(name, status, error) {
|
|
242
|
+
this.run('UPDATE servers SET status = ?, error = ?, last_seen = datetime("now"), updated_at = datetime("now") WHERE name = ?', [status, error ?? null, name]);
|
|
243
|
+
}
|
|
244
|
+
updateServerInfo(name, info, toolCount) {
|
|
245
|
+
this.run('UPDATE servers SET server_info = ?, tool_count = ?, last_seen = datetime("now"), updated_at = datetime("now") WHERE name = ?', [JSON.stringify(info), toolCount, name]);
|
|
246
|
+
}
|
|
247
|
+
// --- Tool Operations ---
|
|
248
|
+
upsertTools(serverName, tools) {
|
|
249
|
+
this.run('DELETE FROM tools WHERE server_name = ?', [serverName]);
|
|
250
|
+
const now = new Date().toISOString();
|
|
251
|
+
for (const tool of tools) {
|
|
252
|
+
const id = `${serverName}:${tool.name}`;
|
|
253
|
+
this.run(`INSERT INTO tools (id, server_name, name, description, input_schema, annotations, discovered_at, last_verified)
|
|
254
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [id, serverName, tool.name, tool.description || '', tool.inputSchema ? JSON.stringify(tool.inputSchema) : null,
|
|
255
|
+
tool.annotations ? JSON.stringify(tool.annotations) : null, now, now]);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
getTool(id) {
|
|
259
|
+
const row = this.get('SELECT * FROM tools WHERE id = ?', [id]);
|
|
260
|
+
return row ? this.toTool(row) : null;
|
|
261
|
+
}
|
|
262
|
+
getToolsByServer(serverName) {
|
|
263
|
+
return this.all('SELECT * FROM tools WHERE server_name = ? ORDER BY name', [serverName])
|
|
264
|
+
.map(r => this.toTool(r));
|
|
265
|
+
}
|
|
266
|
+
getAllTools() {
|
|
267
|
+
return this.all('SELECT * FROM tools ORDER BY server_name, name')
|
|
268
|
+
.map(r => this.toTool(r));
|
|
269
|
+
}
|
|
270
|
+
searchTools(query, limit = 20) {
|
|
271
|
+
if (!query.trim())
|
|
272
|
+
return [];
|
|
273
|
+
const terms = query.toLowerCase().split(/\s+/);
|
|
274
|
+
const tools = this.getAllTools();
|
|
275
|
+
return tools
|
|
276
|
+
.map(tool => {
|
|
277
|
+
let score = 0;
|
|
278
|
+
const nameL = tool.name.toLowerCase();
|
|
279
|
+
const descL = tool.description.toLowerCase();
|
|
280
|
+
for (const term of terms) {
|
|
281
|
+
if (nameL === term)
|
|
282
|
+
score += 10;
|
|
283
|
+
else if (nameL.includes(term))
|
|
284
|
+
score += 5;
|
|
285
|
+
if (descL.includes(term))
|
|
286
|
+
score += 3;
|
|
287
|
+
if (tool.serverName.toLowerCase().includes(term))
|
|
288
|
+
score += 1;
|
|
289
|
+
}
|
|
290
|
+
return { tool, score };
|
|
291
|
+
})
|
|
292
|
+
.filter(s => s.score > 0)
|
|
293
|
+
.sort((a, b) => b.score - a.score)
|
|
294
|
+
.slice(0, limit);
|
|
295
|
+
}
|
|
296
|
+
removeToolsByServer(serverName) {
|
|
297
|
+
this.run('DELETE FROM tools WHERE server_name = ?', [serverName]);
|
|
298
|
+
}
|
|
299
|
+
toolCount() {
|
|
300
|
+
const row = this.get('SELECT COUNT(*) as count FROM tools');
|
|
301
|
+
return row?.count ?? 0;
|
|
302
|
+
}
|
|
303
|
+
// --- Helpers ---
|
|
304
|
+
toServerResult(row) {
|
|
305
|
+
const config = JSON.parse(row.config_json);
|
|
306
|
+
const serverInfo = row.server_info ? JSON.parse(row.server_info) : null;
|
|
307
|
+
return {
|
|
308
|
+
config,
|
|
309
|
+
server: {
|
|
310
|
+
name: row.name,
|
|
311
|
+
status: row.status,
|
|
312
|
+
transport: config.transport.type,
|
|
313
|
+
toolCount: row.tool_count,
|
|
314
|
+
lastSeen: (row.last_seen || row.created_at),
|
|
315
|
+
error: row.error,
|
|
316
|
+
serverInfo,
|
|
317
|
+
},
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
toTool(row) {
|
|
321
|
+
return {
|
|
322
|
+
id: row.id,
|
|
323
|
+
serverName: row.server_name,
|
|
324
|
+
name: row.name,
|
|
325
|
+
description: (row.description || ''),
|
|
326
|
+
inputSchema: row.input_schema ? JSON.parse(row.input_schema) : undefined,
|
|
327
|
+
annotations: row.annotations ? JSON.parse(row.annotations) : undefined,
|
|
328
|
+
discoveredAt: row.discovered_at,
|
|
329
|
+
lastVerified: row.last_verified,
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
getRawDb() {
|
|
333
|
+
return this.db;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
//# sourceMappingURL=database.js.map
|