ft-scout 9.0.7 → 9.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/.firebase/hosting.d2Vi.cache +8 -8
  2. package/AUTONOMOUS_FEATURES.md +1 -1
  3. package/README.md +113 -16
  4. package/bin/src/commands/agent.js +2 -2
  5. package/bin/src/commands/agent.js.map +1 -1
  6. package/bin/src/commands/audit.js +1 -1
  7. package/bin/src/commands/audit.js.map +1 -1
  8. package/bin/src/commands/dashboard.js +1 -1
  9. package/bin/src/commands/dashboard.js.map +1 -1
  10. package/bin/src/commands/mcp.d.ts.map +1 -0
  11. package/bin/src/commands/mcp.js +393 -0
  12. package/bin/src/commands/mcp.js.map +1 -0
  13. package/bin/src/commands/owners.js +1 -1
  14. package/bin/src/commands/owners.js.map +1 -1
  15. package/bin/src/discovery/messages.js +2 -2
  16. package/bin/src/discovery/messages.js.map +1 -1
  17. package/bin/src/discovery/signals.js +3 -3
  18. package/bin/src/discovery/signals.js.map +1 -1
  19. package/bin/src/engine/agentEngine.d.ts.map +1 -1
  20. package/bin/src/engine/agentEngine.js +53 -11
  21. package/bin/src/engine/agentEngine.js.map +1 -1
  22. package/bin/src/engine/runtime/agentRuntime.d.ts.map +1 -1
  23. package/bin/src/engine/runtime/agentRuntime.js +40 -3
  24. package/bin/src/engine/runtime/agentRuntime.js.map +1 -1
  25. package/bin/src/engine/toolRegistry.d.ts.map +1 -1
  26. package/bin/src/engine/toolRegistry.js +13 -0
  27. package/bin/src/engine/toolRegistry.js.map +1 -1
  28. package/bin/src/engine/verifier.js +2 -2
  29. package/bin/src/engine/verifier.js.map +1 -1
  30. package/bin/src/index.js +85 -7
  31. package/bin/src/index.js.map +1 -1
  32. package/bin/src/mcp/client.d.ts.map +1 -0
  33. package/bin/src/mcp/client.js +127 -0
  34. package/bin/src/mcp/client.js.map +1 -0
  35. package/bin/src/mcp/discovery.d.ts.map +1 -0
  36. package/bin/src/mcp/discovery.js +91 -0
  37. package/bin/src/mcp/discovery.js.map +1 -0
  38. package/bin/src/mcp/health.d.ts.map +1 -0
  39. package/bin/src/mcp/health.js +44 -0
  40. package/bin/src/mcp/health.js.map +1 -0
  41. package/bin/src/mcp/index.d.ts.map +1 -0
  42. package/bin/src/mcp/index.js +15 -0
  43. package/bin/src/mcp/index.js.map +1 -0
  44. package/bin/src/mcp/manager.d.ts.map +1 -0
  45. package/bin/src/mcp/manager.js +535 -0
  46. package/bin/src/mcp/manager.js.map +1 -0
  47. package/bin/src/mcp/permissions.d.ts.map +1 -0
  48. package/bin/src/mcp/permissions.js +50 -0
  49. package/bin/src/mcp/permissions.js.map +1 -0
  50. package/bin/src/mcp/persistence.d.ts.map +1 -0
  51. package/bin/src/mcp/persistence.js +156 -0
  52. package/bin/src/mcp/persistence.js.map +1 -0
  53. package/bin/src/mcp/recovery.d.ts.map +1 -0
  54. package/bin/src/mcp/recovery.js +75 -0
  55. package/bin/src/mcp/recovery.js.map +1 -0
  56. package/bin/src/mcp/telemetry.d.ts.map +1 -0
  57. package/bin/src/mcp/telemetry.js +82 -0
  58. package/bin/src/mcp/telemetry.js.map +1 -0
  59. package/bin/src/mcp/toolRouter.d.ts.map +1 -0
  60. package/bin/src/mcp/toolRouter.js +127 -0
  61. package/bin/src/mcp/toolRouter.js.map +1 -0
  62. package/bin/src/mcp/transport.d.ts.map +1 -0
  63. package/bin/src/mcp/transport.js +328 -0
  64. package/bin/src/mcp/transport.js.map +1 -0
  65. package/bin/src/mcp/types.d.ts.map +1 -0
  66. package/bin/src/mcp/types.js +6 -0
  67. package/bin/src/mcp/types.js.map +1 -0
  68. package/bin/src/server/server.d.ts.map +1 -1
  69. package/bin/src/server/server.js +207 -0
  70. package/bin/src/server/server.js.map +1 -1
  71. package/bin/src/utils/branding.js +1 -1
  72. package/bin/src/utils/email.js +4 -4
  73. package/package.json +1 -1
  74. package/web/app.js +1255 -59
  75. package/web/styles.css +1474 -15
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Scout MCP Ecosystem - Persistence & Encrypted Credential Store
3
+ * Manages MCP server definitions and securely encrypts secrets at rest using AES-256-GCM.
4
+ */
5
+ import fs from 'fs';
6
+ import path from 'path';
7
+ import os from 'os';
8
+ import crypto from 'crypto';
9
+ const HOME_FT_DIR = path.join(os.homedir(), '.ft');
10
+ const SERVERS_FILE = path.join(HOME_FT_DIR, 'mcp_servers.json');
11
+ const CREDENTIALS_FILE = path.join(HOME_FT_DIR, 'mcp_credentials.enc');
12
+ // Derive machine-specific key for local AES-256-GCM encryption
13
+ function getEncryptionKey() {
14
+ const machineSalt = 'scout_mcp_secure_v1_encryption_salt';
15
+ const machineId = `${os.hostname()}_${os.userInfo().username}_${os.platform()}`;
16
+ return crypto.pbkdf2Sync(machineId, machineSalt, 100000, 32, 'sha256');
17
+ }
18
+ function ensureDir(dirPath) {
19
+ if (!fs.existsSync(dirPath)) {
20
+ fs.mkdirSync(dirPath, { recursive: true });
21
+ }
22
+ }
23
+ /**
24
+ * Encrypt a plaintext string using AES-256-GCM
25
+ */
26
+ export function encryptSecret(plainText) {
27
+ const key = getEncryptionKey();
28
+ const iv = crypto.randomBytes(12);
29
+ const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
30
+ let encrypted = cipher.update(plainText, 'utf8', 'hex');
31
+ encrypted += cipher.final('hex');
32
+ const authTag = cipher.getAuthTag();
33
+ return `${iv.toString('hex')}:${authTag.toString('hex')}:${encrypted}`;
34
+ }
35
+ /**
36
+ * Decrypt an AES-256-GCM encrypted payload string
37
+ */
38
+ export function decryptSecret(encryptedPayload) {
39
+ try {
40
+ const parts = encryptedPayload.split(':');
41
+ if (parts.length !== 3)
42
+ return '';
43
+ const ivHex = parts[0];
44
+ const authTagHex = parts[1];
45
+ const encryptedHex = parts[2];
46
+ if (!ivHex || !authTagHex || !encryptedHex)
47
+ return '';
48
+ const key = getEncryptionKey();
49
+ const iv = Buffer.from(ivHex, 'hex');
50
+ const authTag = Buffer.from(authTagHex, 'hex');
51
+ const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
52
+ decipher.setAuthTag(authTag);
53
+ let decrypted = decipher.update(encryptedHex, 'hex', 'utf8');
54
+ decrypted += decipher.final('utf8');
55
+ return decrypted;
56
+ }
57
+ catch {
58
+ return '';
59
+ }
60
+ }
61
+ function loadCredentialsMap() {
62
+ if (!fs.existsSync(CREDENTIALS_FILE))
63
+ return {};
64
+ try {
65
+ const raw = fs.readFileSync(CREDENTIALS_FILE, 'utf-8');
66
+ return JSON.parse(raw);
67
+ }
68
+ catch {
69
+ return {};
70
+ }
71
+ }
72
+ function saveCredentialsMap(map) {
73
+ ensureDir(HOME_FT_DIR);
74
+ fs.writeFileSync(CREDENTIALS_FILE, JSON.stringify(map, null, 2), { encoding: 'utf-8', mode: 0o600 });
75
+ }
76
+ /**
77
+ * Save an encrypted secret for an MCP server
78
+ */
79
+ export function saveServerSecret(serverId, secret) {
80
+ if (!secret)
81
+ return;
82
+ const map = loadCredentialsMap();
83
+ map[serverId] = encryptSecret(secret);
84
+ saveCredentialsMap(map);
85
+ }
86
+ /**
87
+ * Retrieve decrypted secret for an MCP server
88
+ */
89
+ export function getServerSecret(serverId) {
90
+ const map = loadCredentialsMap();
91
+ const enc = map[serverId];
92
+ if (!enc)
93
+ return null;
94
+ const dec = decryptSecret(enc);
95
+ return dec || null;
96
+ }
97
+ /**
98
+ * Delete a stored secret for an MCP server
99
+ */
100
+ export function deleteServerSecret(serverId) {
101
+ const map = loadCredentialsMap();
102
+ if (map[serverId]) {
103
+ delete map[serverId];
104
+ saveCredentialsMap(map);
105
+ }
106
+ }
107
+ /**
108
+ * Check if a server has an encrypted secret stored
109
+ */
110
+ export function hasServerSecret(serverId) {
111
+ const map = loadCredentialsMap();
112
+ return Boolean(map[serverId]);
113
+ }
114
+ /**
115
+ * Load all configured MCP servers from disk
116
+ */
117
+ export function loadMCPServers() {
118
+ if (!fs.existsSync(SERVERS_FILE))
119
+ return [];
120
+ try {
121
+ const raw = fs.readFileSync(SERVERS_FILE, 'utf-8');
122
+ const list = JSON.parse(raw);
123
+ if (!Array.isArray(list))
124
+ return [];
125
+ return list.map((server) => {
126
+ server.hasSecret = hasServerSecret(server.id);
127
+ return server;
128
+ });
129
+ }
130
+ catch {
131
+ return [];
132
+ }
133
+ }
134
+ /**
135
+ * Save MCP servers list to disk
136
+ */
137
+ export function saveMCPServers(servers) {
138
+ ensureDir(HOME_FT_DIR);
139
+ // Sanitize before writing: ensure no secrets are stored in mcp_servers.json
140
+ const cleaned = servers.map((s) => sanitizeServerConfig(s));
141
+ fs.writeFileSync(SERVERS_FILE, JSON.stringify(cleaned, null, 2), 'utf-8');
142
+ }
143
+ /**
144
+ * Return a copy of MCPServerConfig safe for client/UI/CLI display (no secrets)
145
+ */
146
+ export function sanitizeServerConfig(server) {
147
+ const clone = JSON.parse(JSON.stringify(server));
148
+ delete clone.token;
149
+ delete clone.key;
150
+ delete clone.secret;
151
+ delete clone.password;
152
+ delete clone.apiKey;
153
+ clone.hasSecret = hasServerSecret(server.id) || Boolean(server.hasSecret);
154
+ return clone;
155
+ }
156
+ //# sourceMappingURL=persistence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence.js","sourceRoot":"","sources":["persistence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["recovery.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,gBAAgB,GACtB,iBAAiB,GACjB,SAAS,GACT,wBAAwB,GACxB,gBAAgB,GAChB,cAAc,GACd,kBAAkB,GAClB,gBAAgB,CAAC;AAEvB,MAAM,WAAW,kBAAkB;IAC/B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,WAAW;IACpB;;OAEG;IACH,OAAc,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,GAAE,OAAe,GAAG,kBAAkB,CAuE5G;CACJ"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Scout MCP Ecosystem - Failure Recovery & Error Classification
3
+ * Implements bounded recovery, error classification, and user-friendly error formatting.
4
+ */
5
+ export class MCPRecovery {
6
+ /**
7
+ * Classify an error encountered during MCP communication or tool execution
8
+ */
9
+ static classifyError(err, serverName, isDestructive = false) {
10
+ const msg = String(err?.message || err || '');
11
+ const lower = msg.toLowerCase();
12
+ if (lower.includes('econnrefused') || lower.includes('failed to fetch') || lower.includes('connection lost') || lower.includes('exited with code') || lower.includes('disconnected')) {
13
+ return {
14
+ category: 'CONNECTION_LOST',
15
+ isRecoverable: true,
16
+ canRetry: !isDestructive,
17
+ userFriendlyMessage: `${serverName} connection was dropped. Scout can attempt to reconnect.`,
18
+ originalError: msg,
19
+ };
20
+ }
21
+ if (lower.includes('timed out') || lower.includes('timeout') || lower.includes('aborterror')) {
22
+ return {
23
+ category: 'TIMEOUT',
24
+ isRecoverable: true,
25
+ canRetry: !isDestructive,
26
+ userFriendlyMessage: `${serverName} took too long to respond. The operation timed out.`,
27
+ originalError: msg,
28
+ };
29
+ }
30
+ if (lower.includes('unauthorized') || lower.includes('401') || lower.includes('403') || lower.includes('forbidden') || lower.includes('auth')) {
31
+ return {
32
+ category: 'AUTHENTICATION_EXPIRED',
33
+ isRecoverable: false,
34
+ canRetry: false,
35
+ userFriendlyMessage: `Authentication for ${serverName} is expired or invalid. Please update credentials in Connections.`,
36
+ originalError: msg,
37
+ };
38
+ }
39
+ if (lower.includes('429') || lower.includes('rate limit') || lower.includes('quota')) {
40
+ return {
41
+ category: 'RATE_LIMITED',
42
+ isRecoverable: true,
43
+ canRetry: false,
44
+ userFriendlyMessage: `${serverName} rate limit exceeded. Please wait a moment before trying again.`,
45
+ originalError: msg,
46
+ };
47
+ }
48
+ if (lower.includes('method not found') || lower.includes('tool not found') || lower.includes('-32601')) {
49
+ return {
50
+ category: 'TOOL_NOT_FOUND',
51
+ isRecoverable: false,
52
+ canRetry: false,
53
+ userFriendlyMessage: `Requested tool is no longer available on ${serverName}. Discovered tools will be refreshed.`,
54
+ originalError: msg,
55
+ };
56
+ }
57
+ if (lower.includes('invalid params') || lower.includes('validation') || lower.includes('-32602')) {
58
+ return {
59
+ category: 'VALIDATION_ERROR',
60
+ isRecoverable: false,
61
+ canRetry: false,
62
+ userFriendlyMessage: `Invalid parameters supplied for ${serverName} tool call.`,
63
+ originalError: msg,
64
+ };
65
+ }
66
+ return {
67
+ category: 'INTERNAL_ERROR',
68
+ isRecoverable: false,
69
+ canRetry: !isDestructive,
70
+ userFriendlyMessage: `An error occurred while executing an operation on ${serverName}.`,
71
+ originalError: msg,
72
+ };
73
+ }
74
+ }
75
+ //# sourceMappingURL=recovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recovery.js","sourceRoot":"","sources":["recovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["telemetry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAYlE;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,CAqB3C;AAED,qBAAa,YAAY;IACrB,OAAc,YAAY,CAAC,KAAK,GAAE,MAAW,GAAG,gBAAgB,EAAE,CASjE;IAED,OAAc,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAUvD;IAED,OAAc,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAatD;CACJ"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Scout MCP Ecosystem - Telemetry & Activity Logger
3
+ * Records observable tool executions and logs without capturing secrets or internal reasoning.
4
+ */
5
+ import fs from 'fs';
6
+ import path from 'path';
7
+ import os from 'os';
8
+ const HOME_FT_DIR = path.join(os.homedir(), '.ft');
9
+ const ACTIVITY_FILE = path.join(HOME_FT_DIR, 'mcp_activity.json');
10
+ const MAX_LOG_ENTRIES = 200;
11
+ function ensureDir(dirPath) {
12
+ if (!fs.existsSync(dirPath)) {
13
+ fs.mkdirSync(dirPath, { recursive: true });
14
+ }
15
+ }
16
+ /**
17
+ * Sanitize an object to remove sensitive keys (auth, token, key, secret, password)
18
+ */
19
+ export function sanitizeData(data) {
20
+ if (!data)
21
+ return data;
22
+ if (typeof data !== 'object')
23
+ return data;
24
+ if (Array.isArray(data)) {
25
+ return data.map((item) => sanitizeData(item));
26
+ }
27
+ const cleaned = {};
28
+ const sensitiveKeys = ['authorization', 'token', 'key', 'secret', 'password', 'apikey', 'credential'];
29
+ for (const [k, v] of Object.entries(data)) {
30
+ if (sensitiveKeys.some((s) => k.toLowerCase().includes(s))) {
31
+ cleaned[k] = '[REDACTED]';
32
+ }
33
+ else if (typeof v === 'string' && v.length > 2000) {
34
+ cleaned[k] = `${v.slice(0, 2000)}... [truncated]`;
35
+ }
36
+ else {
37
+ cleaned[k] = sanitizeData(v);
38
+ }
39
+ }
40
+ return cleaned;
41
+ }
42
+ export class MCPTelemetry {
43
+ static loadActivity(limit = 50) {
44
+ if (!fs.existsSync(ACTIVITY_FILE))
45
+ return [];
46
+ try {
47
+ const raw = fs.readFileSync(ACTIVITY_FILE, 'utf-8');
48
+ const list = JSON.parse(raw);
49
+ return Array.isArray(list) ? list.slice(0, limit) : [];
50
+ }
51
+ catch {
52
+ return [];
53
+ }
54
+ }
55
+ static recordEvent(event) {
56
+ ensureDir(HOME_FT_DIR);
57
+ let list = this.loadActivity(MAX_LOG_ENTRIES);
58
+ list.unshift(event);
59
+ if (list.length > MAX_LOG_ENTRIES) {
60
+ list = list.slice(0, MAX_LOG_ENTRIES);
61
+ }
62
+ try {
63
+ fs.writeFileSync(ACTIVITY_FILE, JSON.stringify(list, null, 2), 'utf-8');
64
+ }
65
+ catch { }
66
+ }
67
+ static recordResult(result) {
68
+ const event = {
69
+ id: result.invocationId,
70
+ timestamp: result.completedAt || new Date().toISOString(),
71
+ serverId: result.serverId,
72
+ serverName: result.serverName,
73
+ toolName: result.toolName,
74
+ status: result.status,
75
+ summary: result.outputSummary || result.inputSummary,
76
+ durationMs: result.executionDurationMs,
77
+ error: result.error,
78
+ };
79
+ this.recordEvent(event);
80
+ }
81
+ }
82
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["telemetry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolRouter.d.ts","sourceRoot":"","sources":["toolRouter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGrE,MAAM,WAAW,mBAAmB;IAChC,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;CAC/B;AAED,qBAAa,aAAa;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAM;IAElD;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;IAoDjC;;OAEG;IACH,OAAc,UAAU,CACpB,QAAQ,EAAE,MAAM,EAChB,gBAAgB,EAAE,eAAe,EAAE,GACpC,mBAAmB,CA4ErB;CACJ"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Scout MCP Ecosystem - Intelligent Capability & Tool Router
3
+ * Selects only relevant MCP capabilities and tools for a given user goal,
4
+ * preventing context-window bloating and reasoning degradation.
5
+ */
6
+ import { MCPPermissionManager } from './permissions.js';
7
+ export class MCPToolRouter {
8
+ static MAX_ROUTED_MCP_TOOLS = 10;
9
+ /**
10
+ * Compute a relevance score for a tool based on user goal and context
11
+ */
12
+ static scoreToolRelevance(tool, server, goalTokens, rawGoalLower) {
13
+ let score = 0;
14
+ const toolNameLower = tool.originalName.toLowerCase();
15
+ const serverNameLower = server.name.toLowerCase();
16
+ const descLower = tool.description.toLowerCase();
17
+ // 1. Direct explicit mention of server name in user request (e.g. "use higgsfield to...", "via motion")
18
+ if (rawGoalLower.includes(serverNameLower)) {
19
+ score += 100;
20
+ }
21
+ // 2. Direct mention of tool name
22
+ if (rawGoalLower.includes(toolNameLower)) {
23
+ score += 80;
24
+ }
25
+ // 3. Domain / Capability affinity rules
26
+ const domainClusters = {
27
+ media_generation: ['video', 'image', 'picture', 'photo', 'audio', 'voice', 'sound', 'render', 'generate', 'animat', 'frame', 'visual', 'ad', 'banner', 'higgsfield'],
28
+ research_analytics: ['competitor', 'research', 'trend', 'analytics', 'market', 'creative', 'metrics', 'motion', 'benchmark', 'intelligence'],
29
+ version_control: ['github', 'gitlab', 'git', 'issue', 'pr', 'pull request', 'commit', 'branch', 'repo', 'repository'],
30
+ design_ui: ['figma', 'sketch', 'mockup', 'design', 'frame', 'canvas', 'component', 'prototype', 'wireframe', 'palette'],
31
+ communication: ['slack', 'discord', 'message', 'chat', 'channel', 'notify', 'alert', 'post', 'webhook'],
32
+ knowledge_docs: ['notion', 'docs', 'wiki', 'page', 'database', 'notes', 'workspace'],
33
+ };
34
+ for (const [_domain, keywords] of Object.entries(domainClusters)) {
35
+ const goalHasDomain = keywords.some((k) => rawGoalLower.includes(k));
36
+ if (goalHasDomain) {
37
+ const toolHasDomain = keywords.some((k) => toolNameLower.includes(k) || descLower.includes(k) || serverNameLower.includes(k));
38
+ if (toolHasDomain) {
39
+ score += 25;
40
+ }
41
+ }
42
+ }
43
+ // 4. Token-level keyword matching
44
+ for (const token of goalTokens) {
45
+ if (token.length < 3)
46
+ continue;
47
+ if (toolNameLower.includes(token))
48
+ score += 15;
49
+ if (descLower.includes(token))
50
+ score += 5;
51
+ if (serverNameLower.includes(token))
52
+ score += 10;
53
+ }
54
+ return score;
55
+ }
56
+ /**
57
+ * Route user goal to the most relevant MCP tools across all connected servers
58
+ */
59
+ static routeTools(userGoal, connectedServers) {
60
+ const rawGoalLower = userGoal.toLowerCase().trim();
61
+ const goalTokens = rawGoalLower
62
+ .replace(/[^a-zA-Z0-9_\s]/g, ' ')
63
+ .split(/\s+/)
64
+ .filter((t) => t.length >= 3);
65
+ // Gather all permitted tools across all connected & enabled servers
66
+ const candidateTools = [];
67
+ for (const server of connectedServers) {
68
+ if (server.status !== 'connected' || server.permissions.enabled === false) {
69
+ continue;
70
+ }
71
+ for (const tool of server.tools) {
72
+ const perm = MCPPermissionManager.checkToolAccess(server, tool);
73
+ if (!perm.allowed)
74
+ continue;
75
+ const score = this.scoreToolRelevance(tool, server, goalTokens, rawGoalLower);
76
+ candidateTools.push({ tool, server, score });
77
+ }
78
+ }
79
+ // Total permitted tools count
80
+ const totalToolsCount = candidateTools.length;
81
+ // If total tools are small (e.g. <= 8), provide all permitted tools without aggressive filtering
82
+ let selected;
83
+ if (totalToolsCount <= 8) {
84
+ selected = candidateTools;
85
+ }
86
+ else {
87
+ // Sort by relevance score descending
88
+ candidateTools.sort((a, b) => b.score - a.score);
89
+ // Filter tools with positive relevance, or take top tools if there's general affinity
90
+ const positiveMatches = candidateTools.filter((c) => c.score > 0);
91
+ if (positiveMatches.length > 0) {
92
+ selected = positiveMatches.slice(0, this.MAX_ROUTED_MCP_TOOLS);
93
+ }
94
+ else {
95
+ // If no specific keyword matched, include up to 5 representative tools (one per active server)
96
+ const seenServers = new Set();
97
+ const diverseSelection = [];
98
+ for (const item of candidateTools) {
99
+ if (!seenServers.has(item.server.id) && diverseSelection.length < 5) {
100
+ seenServers.add(item.server.id);
101
+ diverseSelection.push(item);
102
+ }
103
+ }
104
+ selected = diverseSelection;
105
+ }
106
+ }
107
+ const tools = selected.map((s) => s.tool);
108
+ const activeServerSet = new Set(selected.map((s) => s.server.name));
109
+ const activeServers = Array.from(activeServerSet);
110
+ // Build concise capability representation for system prompt
111
+ const serverSummaries = [];
112
+ for (const sName of activeServers) {
113
+ const serverTools = tools.filter((t) => t.serverName === sName);
114
+ const toolSummary = serverTools.map((t) => t.originalName).join(', ');
115
+ serverSummaries.push(`• ${sName} (${serverTools.length} tools): ${toolSummary}`);
116
+ }
117
+ const capabilitiesSummary = serverSummaries.length > 0
118
+ ? `AVAILABLE EXTERNAL MCP CAPABILITIES:\n${serverSummaries.join('\n')}`
119
+ : '';
120
+ return {
121
+ tools,
122
+ activeServers,
123
+ capabilitiesSummary,
124
+ };
125
+ }
126
+ }
127
+ //# sourceMappingURL=toolRouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolRouter.js","sourceRoot":"","sources":["toolRouter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["transport.ts"],"names":[],"mappings":"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"}