A template for building MCP (Model Context Protocol) client applications, featuring a Vite + TypeScript frontend and an Express backend. Includes OAuth2.1 authentication and ready-to-use APIs for managing and interacting with MCP servers. Easily extensible for custom workflows and integrations.
This MCP client template provides a web interface to manage and interact with MCP servers. It allows users to add MCP servers (stdio, HTTP stream, SSE...
112if (type === 'httpstream' || type === 'sse') {
113 const TransportClass = type === 'httpstream' ? StreamableHTTPClientTransport : SSEClientTransport;
114 const transport = new TransportClass(new URL(command), { authProvider: oauthProvider });
115 ...
116}// Network-exposed MCP backend; any user can add a server with a malicious URL.
38app.post('/add-server', (req, res) => {
39 const { id, command, type, args } = req.body;
40 if (!id || !command || !type) {
41 res.status(400).json({ error: 'Missing required fields' });
42 return;
43 }
44 ...
45 serversJson.servers[id] = {
46 command,
47 type,
48 args: Array.isArray(args) ? args : []
49 };
50 try {
51 fs.writeFileSync(serversPath, JSON.stringify(serversJson, null, 2), 'utf-8');
52 res.json({ success: true });
53 } catch (err) {
54 res.status(500).json({ error: 'Cannot write server config' });
55 }
56});// Network-exposed MCP backend; any user can call /add-server and execute arbitrary commands.
136app.post('/mcp', async (req, res) => {
137 const { server, command, args: argsOverride } = req.body;
138 ...
139 let serverConfig = serversJson[server];
140 if (!serverConfig && serversJson.servers && serversJson.servers[server]) {
141 serverConfig = serversJson.servers[server];
142 }
143 if (!serverConfig) {
144 res.status(404).json({ error: 'Server not found' });
145 return;
146 }
147 if (argsOverride && Array.isArray(argsOverride)) {
148 serverConfig = { ...serverConfig, args: argsOverride };
149 }
150 serverConfig = { name: server, ...serverConfig }
151 globalServersJson[server] = serverConfig;
152 let connection;
153 try {
154 connection = await autoDetectTransport(serverConfig);
155 } catch (err) { ... }// Network-exposed MCP backend; any user can call /mcp with a malicious server name or argsOverride.
38app.post('/add-server', (req, res) => {
39 const { id, command, type, args } = req.body;
40 ...
41});
42app.get('/servers', (req, res) => { ... });
43app.post('/mcp', async (req, res) => { ... });// Network-exposed MCP backend; no authentication required.
120const tokens = globalServersJson.get(serverConfig.name)?.oauthProvider?.getTokens();
121console.log("Access Token:", JSON.stringify(tokens, null, 2));// Network-exposed MCP backend; logs may be accessible to attackers.
29setServerTokens(serverName: string, tokens: any) {
30 this.data.tokens[serverName] = {
31 tokens,
32 lastConnected: new Date().toISOString(),
33 connected: true
34 };
35 this.save();
36}// Network-exposed MCP backend; file system access may be possible via other vulnerabilities.
56serversJson.servers[id] = {
57 command,
58 type,
59 args: Array.isArray(args) ? args : []
60};
61try {
62 fs.writeFileSync(serversPath, JSON.stringify(serversJson, null, 2), 'utf-8');
63 res.json({ success: true });
64} catch (err) { ... }// Network-exposed MCP backend; low risk but should be fixed.