typescript-sdk/scripts/cli.ts

156 lines
4.3 KiB
TypeScript

import express from 'express';
import { Client } from '../src/client/index.js';
import { SSEClientTransport } from '../src/client/sse.js';
import { StdioClientTransport } from '../src/client/stdio.js';
import { Server } from '../src/server/index.js';
import { SSEServerTransport } from '../src/server/sse.js';
import { StdioServerTransport } from '../src/server/stdio.js';
import { ListResourcesResultSchema } from '../src/types.js';
async function runClient(url_or_command: string, args: string[]) {
const client = new Client(
{
name: 'mcp-typescript test client',
version: '0.1.0'
},
{
capabilities: {
sampling: {}
}
}
);
let clientTransport;
let url: URL | undefined = undefined;
try {
url = new URL(url_or_command);
} catch {
// Ignore
}
if (url?.protocol === 'http:' || url?.protocol === 'https:') {
clientTransport = new SSEClientTransport(new URL(url_or_command));
} else if (url?.protocol === 'ws:' || url?.protocol === 'wss:') {
throw new Error('WebSocket URLs are no longer supported. Use http(s) or stdio instead.');
} else {
clientTransport = new StdioClientTransport({
command: url_or_command,
args
});
}
console.log('Connected to server.');
await client.connect(clientTransport);
console.log('Initialized.');
await client.request({ method: 'resources/list' }, ListResourcesResultSchema);
await client.close();
console.log('Closed.');
}
async function runServer(port: number | null) {
if (port !== null) {
const app = express();
let servers: Server[] = [];
app.get('/sse', async (req, res) => {
console.log('Got new SSE connection');
const transport = new SSEServerTransport('/message', res);
const server = new Server(
{
name: 'mcp-typescript test server',
version: '0.1.0'
},
{
capabilities: {}
}
);
servers.push(server);
server.onclose = () => {
console.log('SSE connection closed');
servers = servers.filter(s => s !== server);
};
await server.connect(transport);
});
app.post('/message', async (req, res) => {
console.log('Received message');
const sessionId = req.query.sessionId as string;
const transport = servers.map(s => s.transport as SSEServerTransport).find(t => t.sessionId === sessionId);
if (!transport) {
res.status(404).send('Session not found');
return;
}
await transport.handlePostMessage(req, res);
});
app.listen(port, error => {
if (error) {
console.error('Failed to start server:', error);
process.exit(1);
}
console.log(`Server running on http://localhost:${port}/sse`);
});
} else {
const server = new Server(
{
name: 'mcp-typescript test server',
version: '0.1.0'
},
{
capabilities: {
prompts: {},
resources: {},
tools: {},
logging: {}
}
}
);
const transport = new StdioServerTransport();
await server.connect(transport);
console.log('Server running on stdio');
}
}
const args = process.argv.slice(2);
const command = args[0];
switch (command) {
case 'client':
if (args.length < 2) {
console.error('Usage: client <server_url_or_command> [args...]');
process.exit(1);
}
runClient(args[1], args.slice(2)).catch(error => {
console.error(error);
process.exit(1);
});
break;
case 'server': {
const port = args[1] ? parseInt(args[1]) : null;
runServer(port).catch(error => {
console.error(error);
process.exit(1);
});
break;
}
default:
console.error('Unrecognized command:', command);
}