@mcp-shark/mcp-shark 1.4.0 → 1.4.2

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 (31) hide show
  1. package/README.md +16 -1
  2. package/bin/mcp-shark.js +179 -53
  3. package/mcp-server/lib/auditor/audit.js +12 -4
  4. package/mcp-server/lib/server/external/kv.js +17 -28
  5. package/mcp-server/lib/server/internal/handlers/prompts-get.js +14 -6
  6. package/mcp-server/lib/server/internal/handlers/prompts-list.js +9 -4
  7. package/mcp-server/lib/server/internal/handlers/resources-list.js +9 -4
  8. package/mcp-server/lib/server/internal/handlers/resources-read.js +13 -3
  9. package/mcp-server/lib/server/internal/handlers/tools-call.js +12 -8
  10. package/mcp-server/lib/server/internal/handlers/tools-list.js +4 -3
  11. package/mcp-server/lib/server/internal/run.js +1 -1
  12. package/mcp-server/lib/server/internal/server.js +10 -10
  13. package/mcp-server/lib/server/internal/session.js +14 -6
  14. package/package.json +4 -2
  15. package/ui/server/routes/composite.js +16 -0
  16. package/ui/server/routes/playground.js +45 -14
  17. package/ui/server/utils/config-update.js +136 -109
  18. package/ui/server.js +1 -0
  19. package/ui/src/components/GroupedByMcpView.jsx +0 -6
  20. package/ui/src/components/McpPlayground/PromptsSection/PromptItem.jsx +46 -21
  21. package/ui/src/components/McpPlayground/PromptsSection/PromptsList.jsx +10 -8
  22. package/ui/src/components/McpPlayground/ResourcesSection/ResourceItem.jsx +60 -32
  23. package/ui/src/components/McpPlayground/ResourcesSection/ResourcesList.jsx +10 -8
  24. package/ui/src/components/McpPlayground/ToolsSection/ToolItem.jsx +46 -21
  25. package/ui/src/components/McpPlayground/ToolsSection/ToolsList.jsx +10 -8
  26. package/ui/src/components/McpPlayground/hooks/useMcpDataLoader.js +107 -0
  27. package/ui/src/components/McpPlayground/hooks/useMcpRequest.js +65 -0
  28. package/ui/src/components/McpPlayground/hooks/useMcpServerStatus.js +70 -0
  29. package/ui/src/components/McpPlayground/useMcpPlayground.js +68 -137
  30. package/ui/src/components/McpPlayground.jsx +100 -21
  31. package/ui/src/utils/requestUtils.js +5 -4
package/README.md CHANGED
@@ -66,11 +66,20 @@ Or if installed locally:
66
66
  npx @mcp-shark/mcp-shark
67
67
  ```
68
68
 
69
+ **Open browser automatically:**
70
+
71
+ ```bash
72
+ mcp-shark --open
73
+ # or
74
+ mcp-shark -o
75
+ ```
76
+
69
77
  The UI will automatically:
70
78
 
71
79
  - Install dependencies if needed
72
80
  - Build the frontend if needed
73
81
  - Start the server on `http://localhost:9853`
82
+ - Optionally open your browser automatically (with `--open` flag)
74
83
 
75
84
  Open your browser to `http://localhost:9853` to access the MCP Shark interface.
76
85
 
@@ -331,8 +340,14 @@ No manual configuration editing required - MCP Shark handles everything for you.
331
340
  mcp-shark
332
341
  ```
333
342
 
343
+ Or to automatically open your browser:
344
+
345
+ ```bash
346
+ mcp-shark --open
347
+ ```
348
+
334
349
  3. **Open your browser:**
335
- Navigate to `http://localhost:9853`
350
+ Navigate to `http://localhost:9853` (or it will open automatically with `--open` flag)
336
351
 
337
352
  4. **Interactive Tour**: On first launch, you'll see an interactive tour - follow it to get started
338
353
 
package/bin/mcp-shark.js CHANGED
@@ -3,67 +3,110 @@
3
3
  import { spawn } from 'node:child_process';
4
4
  import { fileURLToPath } from 'node:url';
5
5
  import { dirname, join, resolve } from 'node:path';
6
- import { existsSync } from 'node:fs';
6
+ import { existsSync, readFileSync } from 'node:fs';
7
+ import { Command } from 'commander';
8
+ import open from 'open';
9
+
10
+ const SERVER_URL = 'http://localhost:9853';
11
+ const BROWSER_OPEN_DELAY = 1000;
7
12
 
8
13
  const __filename = fileURLToPath(import.meta.url);
9
14
  const __dirname = dirname(__filename);
10
15
  const rootDir = resolve(__dirname, '..');
11
- const uiDir = join(rootDir, 'ui');
12
16
 
13
- // Check if UI directory exists
14
- if (!existsSync(uiDir)) {
15
- console.error('Error: UI directory not found. Please ensure you are in the correct directory.');
16
- process.exit(1);
17
- }
17
+ /**
18
+ * Display welcome banner
19
+ */
20
+ function displayWelcomeBanner() {
21
+ const pkgPath = join(rootDir, 'package.json');
22
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
23
+ const version = pkg.version;
18
24
 
19
- // Check if node_modules exists in root directory
20
- const rootNodeModules = join(rootDir, 'node_modules');
21
- if (!existsSync(rootNodeModules)) {
22
- console.log('Installing dependencies...');
23
- const installProcess = spawn('npm', ['install'], {
24
- cwd: rootDir,
25
- stdio: 'inherit',
26
- shell: true,
27
- });
25
+ const banner = `
26
+ ███╗ ███╗ ██████╗ ██████╗ ███████╗██╗ ██╗ █████╗ ██████╗ ██╗ ██╗
27
+ ████╗ ████║██╔════╝██╔══██╗ ██╔════╝██║ ██║██╔══██╗██╔══██╗██║ ██╔╝
28
+ ██╔████╔██║██║ ██████╔╝ ███████╗███████║███████║██████╔╝█████╔╝
29
+ ██║╚██╔╝██║██║ ██╔═══╝ ╚════██║██╔══██║██╔══██║██╔══██╗██╔═██╗
30
+ ██║ ╚═╝ ██║╚██████╗██║ ███████║██║ ██║██║ ██║██║ ██║██║ ██╗
31
+ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝
32
+
33
+ Aggregate multiple MCP servers into a unified interface
34
+ Version: ${version} | Homepage: https://mcpshark.sh
35
+ `;
28
36
 
29
- installProcess.on('close', (code) => {
30
- if (code !== 0) {
31
- console.error('Failed to install dependencies');
32
- process.exit(1);
33
- }
34
- console.log('Dependencies installed successfully!\n');
35
- startUIServer();
36
- });
37
- } else {
38
- startUIServer();
37
+ console.log(banner);
39
38
  }
40
39
 
41
- function startUIServer() {
42
- // Check if dist directory exists (production build)
43
- const distDir = join(uiDir, 'dist');
44
- if (!existsSync(distDir)) {
45
- console.log('Building UI for production...');
46
- const buildProcess = spawn('npm', ['run', 'build'], {
47
- cwd: uiDir,
40
+ const uiDir = join(rootDir, 'ui');
41
+ const distDir = join(uiDir, 'dist');
42
+ const rootNodeModules = join(rootDir, 'node_modules');
43
+
44
+ /**
45
+ * Run a command and return a promise that resolves when it completes
46
+ */
47
+ function runCommand(command, args, options) {
48
+ return new Promise((resolve, reject) => {
49
+ const process = spawn(command, args, {
50
+ ...options,
48
51
  stdio: 'inherit',
49
52
  shell: true,
50
53
  });
51
54
 
52
- buildProcess.on('close', (code) => {
55
+ process.on('close', (code) => {
53
56
  if (code !== 0) {
54
- console.error('Failed to build UI');
55
- process.exit(1);
57
+ reject(new Error(`Command failed with exit code ${code}`));
58
+ } else {
59
+ resolve();
56
60
  }
57
- runServer();
58
61
  });
59
- } else {
60
- runServer();
62
+
63
+ process.on('error', (error) => {
64
+ reject(error);
65
+ });
66
+ });
67
+ }
68
+
69
+ /**
70
+ * Install dependencies in the root directory
71
+ */
72
+ async function installDependencies() {
73
+ console.log('Installing dependencies...');
74
+ try {
75
+ await runCommand('npm', ['install'], { cwd: rootDir });
76
+ console.log('Dependencies installed successfully!\n');
77
+ } catch (error) {
78
+ console.error('Failed to install dependencies:', error.message);
79
+ process.exit(1);
61
80
  }
62
81
  }
63
82
 
64
- function runServer() {
83
+ /**
84
+ * Build the UI for production
85
+ */
86
+ async function buildUI() {
87
+ console.log('Building UI for production...');
88
+ try {
89
+ await runCommand('npm', ['run', 'build'], { cwd: uiDir });
90
+ } catch (error) {
91
+ console.error('Failed to build UI:', error.message);
92
+ process.exit(1);
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Open the browser after a short delay
98
+ */
99
+ async function openBrowser() {
100
+ await new Promise((resolve) => setTimeout(resolve, BROWSER_OPEN_DELAY));
101
+ open(SERVER_URL);
102
+ }
103
+
104
+ /**
105
+ * Start the UI server
106
+ */
107
+ async function startServer(shouldOpenBrowser = false) {
65
108
  console.log('Starting MCP Shark UI server...');
66
- console.log('Open http://localhost:9853 in your browser');
109
+ console.log(`Open ${SERVER_URL} in your browser`);
67
110
  console.log('Press Ctrl+C to stop\n');
68
111
 
69
112
  const serverProcess = spawn('node', ['server.js'], {
@@ -72,22 +115,105 @@ function runServer() {
72
115
  shell: true,
73
116
  });
74
117
 
118
+ if (shouldOpenBrowser) {
119
+ await openBrowser();
120
+ }
121
+
122
+ let isShuttingDown = false;
123
+
75
124
  serverProcess.on('close', (code) => {
76
- if (code !== 0 && code !== null) {
77
- console.error(`Server exited with code ${code}`);
78
- process.exit(code);
125
+ if (!isShuttingDown) {
126
+ if (code !== 0 && code !== null) {
127
+ console.error(`Server exited with code ${code}`);
128
+ process.exit(code);
129
+ }
130
+ } else {
131
+ process.exit(0);
79
132
  }
80
133
  });
81
134
 
82
135
  // Handle process termination
83
- process.on('SIGINT', () => {
84
- console.log('\nShutting down...');
85
- serverProcess.kill('SIGINT');
86
- process.exit(0);
87
- });
136
+ const shutdown = async (signal) => {
137
+ if (isShuttingDown) return;
138
+ isShuttingDown = true;
88
139
 
89
- process.on('SIGTERM', () => {
90
- serverProcess.kill('SIGTERM');
91
- process.exit(0);
92
- });
140
+ console.log('Shutting down...');
141
+
142
+ // Send signal to child process
143
+ serverProcess.kill(signal);
144
+
145
+ // Wait for child process to exit, with timeout
146
+ const timeout = setTimeout(() => {
147
+ console.log('Forcefully terminating server process...');
148
+ serverProcess.kill('SIGKILL');
149
+ process.exit(1);
150
+ }, 5000);
151
+
152
+ serverProcess.once('close', () => {
153
+ clearTimeout(timeout);
154
+ process.exit(0);
155
+ });
156
+ };
157
+
158
+ process.on('SIGINT', () => shutdown('SIGINT'));
159
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
160
+ }
161
+
162
+ /**
163
+ * Validate that required directories exist
164
+ */
165
+ function validateDirectories() {
166
+ if (!existsSync(uiDir)) {
167
+ console.error('Error: UI directory not found. Please ensure you are in the correct directory.');
168
+ process.exit(1);
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Ensure dependencies are installed
174
+ */
175
+ async function ensureDependencies() {
176
+ if (!existsSync(rootNodeModules)) {
177
+ await installDependencies();
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Ensure UI is built
183
+ */
184
+ async function ensureUIBuilt() {
185
+ if (!existsSync(distDir)) {
186
+ await buildUI();
187
+ }
93
188
  }
189
+
190
+ /**
191
+ * Main execution function
192
+ */
193
+ async function main() {
194
+ // Display welcome banner
195
+ displayWelcomeBanner();
196
+
197
+ // Parse command line options
198
+ const program = new Command();
199
+ program.option('-o, --open', 'Open the browser', false).parse(process.argv);
200
+
201
+ const options = program.opts();
202
+
203
+ // Validate environment
204
+ validateDirectories();
205
+
206
+ // Ensure dependencies are installed
207
+ await ensureDependencies();
208
+
209
+ // Ensure UI is built
210
+ await ensureUIBuilt();
211
+
212
+ // Start the server
213
+ await startServer(options.open);
214
+ }
215
+
216
+ main().catch((error) => {
217
+ console.error('Unexpected error:', error);
218
+ process.exit(1);
219
+ });
@@ -135,14 +135,22 @@ export async function withAuditRequestResponseHandler(
135
135
  transport,
136
136
  req,
137
137
  res,
138
- auditLogger
138
+ auditLogger,
139
+ requestedMcpServer,
140
+ initialSessionId
139
141
  ) {
140
142
  const reqBuf = await readBody(req);
141
143
  const reqJsonRpc = tryParseJsonRpc(reqBuf);
142
144
 
143
145
  // Extract session ID from request
144
146
  // If no session ID exists, it's an initiation request
145
- const sessionId = getSessionFromRequest(req);
147
+ const sessionIdFromRequest = getSessionFromRequest(req);
148
+ const sessionId =
149
+ sessionIdFromRequest === null ||
150
+ sessionIdFromRequest === undefined ||
151
+ sessionIdFromRequest === ''
152
+ ? initialSessionId
153
+ : sessionIdFromRequest;
146
154
 
147
155
  // Extract request body as string
148
156
  const reqBodyStr = reqBuf.toString('utf8');
@@ -161,7 +169,7 @@ export async function withAuditRequestResponseHandler(
161
169
  headers: req.headers,
162
170
  body: reqBodyJson || reqBodyStr,
163
171
  userAgent: req.headers['user-agent'] || req.headers['User-Agent'] || null,
164
- remoteAddress: req.socket?.remoteAddress || null,
172
+ remoteAddress: requestedMcpServer,
165
173
  sessionId: sessionId || null,
166
174
  });
167
175
 
@@ -223,6 +231,6 @@ export async function withAuditRequestResponseHandler(
223
231
  jsonrpcId,
224
232
  sessionId: sessionId || null,
225
233
  userAgent: req.headers['user-agent'] || req.headers['User-Agent'] || null,
226
- remoteAddress: req.socket?.remoteAddress || null,
234
+ remoteAddress: requestedMcpServer || null,
227
235
  });
228
236
  }
@@ -1,14 +1,5 @@
1
1
  const kv = new Map();
2
2
 
3
- function buildName(name, typeName) {
4
- return `${name}.${typeName}`;
5
- }
6
-
7
- export function extractName(name) {
8
- const [serverName, typeName] = name.split('.');
9
- return { serverName, typeName };
10
- }
11
-
12
3
  export function buildKv(downstreamServers) {
13
4
  for (const downstreamServer of downstreamServers) {
14
5
  const {
@@ -43,16 +34,16 @@ export function buildKv(downstreamServers) {
43
34
  resourcesMap,
44
35
  promptsMap,
45
36
  tools: tools.map(tool => {
46
- return { ...tool, name: buildName(name, tool.name) };
37
+ return { ...tool, name: tool.name };
47
38
  }),
48
39
  resources: resources.map(resource => {
49
40
  return {
50
41
  ...resource,
51
- name: buildName(name, resource.name),
42
+ name: resource.name,
52
43
  };
53
44
  }),
54
45
  prompts: prompts.map(prompt => {
55
- return { ...prompt, name: buildName(name, prompt.name) };
46
+ return { ...prompt, name: prompt.name };
56
47
  }),
57
48
  });
58
49
  }
@@ -61,42 +52,40 @@ export function buildKv(downstreamServers) {
61
52
  return kv;
62
53
  }
63
54
 
64
- export function getBy(database, calledName, action) {
65
- const { serverName, typeName } = extractName(calledName);
66
- if (!serverName || !typeName) {
67
- return null;
68
- }
69
- const entry = database.get(serverName);
55
+ export function getBy(database, requestedMcpServer, calledName, action) {
56
+ const entry = database.get(requestedMcpServer);
70
57
  if (!entry) {
71
58
  return null;
72
59
  }
73
60
 
74
61
  // Type-based lookup
75
62
  if (action === 'getTools') {
76
- return entry.toolsMap.get(typeName);
63
+ return entry.toolsMap.get(calledName);
77
64
  }
78
65
  if (action === 'getResources') {
79
- return entry.resourcesMap.get(typeName);
66
+ return entry.resourcesMap.get(calledName);
80
67
  }
81
68
  if (action === 'getPrompts') {
82
- return entry.promptsMap.get(typeName);
69
+ return entry.promptsMap.get(calledName);
83
70
  }
84
71
 
85
72
  // Action-based lookup
86
73
  if (action === 'callTool') {
87
- return entry.toolsMap.get(typeName);
74
+ return entry.toolsMap.get(calledName);
88
75
  }
89
76
  if (action === 'readResource') {
90
- return entry.resourcesMap.get(typeName);
77
+ return entry.resourcesMap.get(calledName);
91
78
  }
92
79
  if (action === 'getPrompt') {
93
- return entry.promptsMap.get(typeName);
80
+ return entry.promptsMap.get(calledName);
94
81
  }
95
82
  return null;
96
83
  }
97
84
 
98
- export function listAll(database, type) {
99
- return Array.from(database.values())
100
- .map(entry => entry[type])
101
- .flat();
85
+ export function listAll(database, requestedMcpServer, type) {
86
+ const serverEntry = database.get(requestedMcpServer);
87
+ if (!serverEntry) {
88
+ return [];
89
+ }
90
+ return serverEntry[type];
102
91
  }
@@ -1,20 +1,28 @@
1
- import { getBy, extractName } from '../../external/kv.js';
1
+ import { getBy } from '../../external/kv.js';
2
2
  import { InternalServerError } from './error.js';
3
3
 
4
- export function createPromptsGetHandler(logger, mcpServers) {
4
+ export function createPromptsGetHandler(
5
+ logger,
6
+ mcpServers,
7
+ requestedMcpServer
8
+ ) {
5
9
  return async req => {
6
10
  const name = req.params.name;
7
11
  const promptArgs = req?.params?.arguments || {};
8
12
  logger.debug('Prompt get', name, promptArgs);
9
13
 
10
- const { typeName } = extractName(name);
11
-
12
- const getPrompt = getBy(mcpServers, name, 'getPrompt', promptArgs);
14
+ const getPrompt = getBy(
15
+ mcpServers,
16
+ requestedMcpServer,
17
+ name,
18
+ 'getPrompt',
19
+ promptArgs
20
+ );
13
21
  if (!getPrompt) {
14
22
  throw new InternalServerError(`Prompt not found: ${name}`);
15
23
  }
16
24
 
17
- const result = await getPrompt(typeName, promptArgs);
25
+ const result = await getPrompt(name, promptArgs);
18
26
  logger.debug('Prompt get result', result);
19
27
 
20
28
  return result;
@@ -1,10 +1,15 @@
1
1
  import { listAll } from '../../external/kv.js';
2
2
 
3
- export function createPromptsListHandler(logger, mcpServers) {
4
- return async _req => {
5
- logger.debug('Prompts list');
3
+ export function createPromptsListHandler(
4
+ logger,
5
+ mcpServers,
6
+ requestedMcpServer
7
+ ) {
8
+ return async req => {
9
+ const path = req.path;
10
+ logger.debug('Prompts list', path);
6
11
 
7
- const res = await listAll(mcpServers, 'prompts');
12
+ const res = await listAll(mcpServers, requestedMcpServer, 'prompts');
8
13
  const result = Array.isArray(res) ? { prompts: res } : res;
9
14
 
10
15
  return result;
@@ -1,10 +1,15 @@
1
1
  import { listAll } from '../../external/kv.js';
2
2
 
3
- export function createResourcesListHandler(logger, mcpServers) {
4
- return async _req => {
5
- logger.debug('Resources list');
3
+ export function createResourcesListHandler(
4
+ logger,
5
+ mcpServers,
6
+ requestedMcpServer
7
+ ) {
8
+ return async req => {
9
+ const path = req.path;
10
+ logger.debug('Resources list', path);
6
11
 
7
- const res = await listAll(mcpServers, 'resources');
12
+ const res = await listAll(mcpServers, requestedMcpServer, 'resources');
8
13
  const result = Array.isArray(res) ? { resources: res } : res;
9
14
 
10
15
  return result;
@@ -1,12 +1,22 @@
1
1
  import { getBy } from '../../external/kv.js';
2
2
  import { InternalServerError } from './error.js';
3
3
 
4
- export function createResourcesReadHandler(logger, mcpServers) {
4
+ export function createResourcesReadHandler(
5
+ logger,
6
+ mcpServers,
7
+ requestedMcpServer
8
+ ) {
5
9
  return async req => {
10
+ const path = req.path;
6
11
  const uri = req.params.uri;
7
- logger.debug('Resource read', uri);
12
+ logger.debug('Resource read', path, uri);
8
13
 
9
- const readResource = getBy(mcpServers, uri, 'readResource');
14
+ const readResource = getBy(
15
+ mcpServers,
16
+ requestedMcpServer,
17
+ uri,
18
+ 'readResource'
19
+ );
10
20
  if (!readResource) {
11
21
  throw new InternalServerError(`Resource not found: ${uri}`);
12
22
  }
@@ -1,24 +1,28 @@
1
- import { getBy, extractName } from '../../external/kv.js';
1
+ import { getBy } from '../../external/kv.js';
2
2
  import { InternalServerError } from './error.js';
3
3
 
4
4
  const isAsyncIterable = v => v && typeof v[Symbol.asyncIterator] === 'function';
5
5
 
6
- export function createToolsCallHandler(logger, mcpServers) {
6
+ export function createToolsCallHandler(logger, mcpServers, requestedMcpServer) {
7
7
  return async req => {
8
+ const path = req.path;
8
9
  const { name, arguments: args } = req.params;
9
- logger.debug('Tool call', name, args);
10
+ logger.debug('Tool call', path, name, args);
10
11
 
11
- // Extract real server name from concatenated name
12
- const { typeName } = extractName(name);
13
-
14
- const callTool = getBy(mcpServers, name, 'callTool', args || {});
12
+ const callTool = getBy(
13
+ mcpServers,
14
+ requestedMcpServer,
15
+ name,
16
+ 'callTool',
17
+ args || {}
18
+ );
15
19
  if (!callTool) {
16
20
  throw new InternalServerError(`Tool not found: ${name}`);
17
21
  }
18
22
 
19
23
  const result = await callTool({
20
24
  ...req.params,
21
- name: typeName,
25
+ name,
22
26
  });
23
27
  logger.debug('Tool call result', result);
24
28
 
@@ -1,10 +1,11 @@
1
1
  import { listAll } from '../../external/kv.js';
2
2
 
3
- export function createToolsListHandler(logger, mcpServers) {
3
+ export function createToolsListHandler(logger, mcpServers, requestedMcpServer) {
4
4
  return async req => {
5
- logger.debug('Listing tools', req);
5
+ const path = req.path;
6
+ logger.debug('Listing tools', path);
6
7
 
7
- const res = await listAll(mcpServers, 'tools');
8
+ const res = await listAll(mcpServers, requestedMcpServer, 'tools');
8
9
  logger.debug('Tools list result', res);
9
10
 
10
11
  const result = Array.isArray(res) ? { tools: res } : res;
@@ -22,7 +22,7 @@ export function getInternalServer(
22
22
  })
23
23
  );
24
24
 
25
- app.all('/mcp', async (req, res) => {
25
+ app.all('/mcp/*', async (req, res) => {
26
26
  await withSession(
27
27
  serverFactory,
28
28
  withAuditRequestResponseHandler,
@@ -15,49 +15,49 @@ import { createPromptsListHandler } from './handlers/prompts-list.js';
15
15
  import { createPromptsGetHandler } from './handlers/prompts-get.js';
16
16
  import { createResourcesListHandler } from './handlers/resources-list.js';
17
17
  import { createResourcesReadHandler } from './handlers/resources-read.js';
18
- import { SERVER_NAME } from './handlers/common.js';
19
18
 
20
- export function createInternalServer(logger, mcpServers) {
19
+ export function createInternalServer(logger, mcpServers, requestedMcpServer) {
21
20
  // create MCP server
22
21
  const server = new Server(
23
- { name: SERVER_NAME, version: '1.0.0' },
22
+ { name: requestedMcpServer, version: '1.0.0' },
24
23
  { capabilities: { tools: {}, prompts: {}, resources: {} } }
25
24
  );
26
25
 
27
26
  // Register handlers
28
27
  server.setRequestHandler(
29
28
  ListToolsRequestSchema,
30
- createToolsListHandler(logger, mcpServers)
29
+ createToolsListHandler(logger, mcpServers, requestedMcpServer)
31
30
  );
32
31
 
33
32
  server.setRequestHandler(
34
33
  CallToolRequestSchema,
35
- createToolsCallHandler(logger, mcpServers)
34
+ createToolsCallHandler(logger, mcpServers, requestedMcpServer)
36
35
  );
37
36
 
38
37
  server.setRequestHandler(
39
38
  ListPromptsRequestSchema,
40
- createPromptsListHandler(logger, mcpServers)
39
+ createPromptsListHandler(logger, mcpServers, requestedMcpServer)
41
40
  );
42
41
 
43
42
  server.setRequestHandler(
44
43
  GetPromptRequestSchema,
45
- createPromptsGetHandler(logger, mcpServers)
44
+ createPromptsGetHandler(logger, mcpServers, requestedMcpServer)
46
45
  );
47
46
 
48
47
  server.setRequestHandler(
49
48
  ListResourcesRequestSchema,
50
- createResourcesListHandler(logger, mcpServers)
49
+ createResourcesListHandler(logger, mcpServers, requestedMcpServer)
51
50
  );
52
51
 
53
52
  server.setRequestHandler(
54
53
  ReadResourceRequestSchema,
55
- createResourcesReadHandler(logger, mcpServers)
54
+ createResourcesReadHandler(logger, mcpServers, requestedMcpServer)
56
55
  );
57
56
 
58
57
  return server;
59
58
  }
60
59
 
61
60
  export function createInternalServerFactory(logger, mcpServers) {
62
- return () => createInternalServer(logger, mcpServers);
61
+ return requestedMcpServer =>
62
+ createInternalServer(logger, mcpServers, requestedMcpServer);
63
63
  }