download
Download music files from Soulseek peers by specifying the username and file path from search results.
Instructions
Download a file from a Soulseek peer. Use the username and filename from search results.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| username | Yes | Username of the peer to download from | |
| filename | Yes | Full file path from search results |
Implementation Reference
- src/index.ts:158-170 (handler)MCP tool handler for 'download': parses input with downloadSchema, calls soulseekClient.download(), formats and returns success message with file details.case 'download': { const parsed = downloadSchema.parse(args); const result = await soulseekClient.download(parsed.username, parsed.filename); return { content: [ { type: 'text', text: `Download complete!\n\nFile: ${result.filename}\nSize: ${formatSize(result.size)}\nSaved to: ${result.filePath}`, }, ], }; }
- src/index.ts:16-19 (schema)Zod schema for validating 'download' tool input arguments: username and filename.const downloadSchema = z.object({ username: z.string().describe('Username of the peer to download from'), filename: z.string().describe('Full file path from search results'), });
- src/index.ts:92-109 (registration)Registration of 'download' tool in ListToolsRequestSchema handler: defines name, description, and inputSchema.{ name: 'download', description: 'Download a file from a Soulseek peer. Use the username and filename from search results.', inputSchema: { type: 'object', properties: { username: { type: 'string', description: 'Username of the peer to download from', }, filename: { type: 'string', description: 'Full file path from search results', }, }, required: ['username', 'filename'], }, },
- src/soulseek-client.ts:113-163 (helper)Core download implementation in SoulseekClientWrapper: ensures connection, creates download dir, downloads via SlskClient, pipes stream to file, returns DownloadResult.async download(username: string, filename: string): Promise<DownloadResult> { await this.ensureConnected(); if (!this.client) { throw new Error('Client not connected'); } // Ensure download directory exists await fs.promises.mkdir(this.downloadPath, { recursive: true }); // Extract just the filename from the full path const basename = path.basename(filename.replace(/\\/g, '/')); const filePath = path.join(this.downloadPath, basename); try { const download = await this.client.download(username, filename); // Write the stream to file const writeStream = fs.createWriteStream(filePath); return new Promise((resolve, reject) => { let totalBytes = 0; download.stream.on('data', (chunk: Buffer) => { totalBytes += chunk.length; }); download.stream.pipe(writeStream); download.stream.on('end', () => { console.error(`[Soulseek] Download complete: ${basename} (${totalBytes} bytes)`); resolve({ success: true, filePath, filename: basename, size: totalBytes, }); }); download.stream.on('error', (err: Error) => { reject(new Error(`Download stream error: ${err.message}`)); }); writeStream.on('error', (err: Error) => { reject(new Error(`Write error: ${err.message}`)); }); }); } catch (error) { throw new Error(`Download failed: ${error instanceof Error ? error.message : String(error)}`); } }
- src/soulseek-client.ts:16-21 (schema)TypeScript interface defining the structure of the download result returned by the download helper.export interface DownloadResult { success: boolean; filePath: string; filename: string; size: number; }