Skip to main content
Glama

Storacha MCP Storage Server

Official
by storacha
sse-mcp-server.test.ts7.07 kB
import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'; import path from 'path'; import fs from 'fs/promises'; import { fileURLToPath } from 'url'; import { getTestEnv, TEST_FILEPATH } from './test-config.js'; import { ChildProcess } from 'child_process'; import { spawn } from 'child_process'; // Get directory name in ESM const __dirname = path.dirname(fileURLToPath(import.meta.url)); // Test configuration const PORT = 3002; // Specific port for SSE tests const TEST_HOST = 'localhost'; // Skip tests if running in CI environment // These tests require specific environment configuration and external services // that might not be available in CI environments const isCI = process.env.CI === 'true'; (isCI ? describe.skip : describe)('MCP Server SSE Integration Tests', () => { let client: Client; let tempFilePath: string; let serverProcess: ChildProcess; let clientTransport: SSEClientTransport; // Create a temporary test file and start server beforeAll(async () => { // Create a temporary file path tempFilePath = path.join(__dirname, '..', '..', 'temp-test-file.txt'); await fs.writeFile(tempFilePath, 'This is a test file', 'utf8'); // Start server as a separate process console.log('Starting SSE server process...'); serverProcess = spawn('node', ['dist/index.js'], { env: { ...process.env, ...getTestEnv(), MCP_TRANSPORT_MODE: 'sse', // Set SSE mode MCP_SERVER_PORT: PORT.toString(), // Use the correct environment variable name }, stdio: 'pipe', }); // Log server output for debugging serverProcess.stdout?.on('data', (data: Buffer) => { console.log(`Server stdout: ${data.toString()}`); }); serverProcess.stderr?.on('data', (data: Buffer) => { console.log(`Server stderr: ${data.toString()}`); }); // Wait for server to start await new Promise(resolve => setTimeout(resolve, 2000)); // Create client that connects to server in SSE mode clientTransport = new SSEClientTransport(new URL(`http://${TEST_HOST}:${PORT}/sse`)); client = new Client( { name: 'test-client', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); // Connect to the server await client.connect(clientTransport); // Wait a moment for the connection to establish await new Promise(resolve => setTimeout(resolve, 1000)); }, 15000); // Increase timeout for server startup afterAll(async () => { // Clean up temporary file try { await fs.unlink(tempFilePath); } catch (e) { // Ignore errors if file doesn't exist } // Close the transport await clientTransport.close(); // Kill the server process if (serverProcess) { serverProcess.kill(); } }); it('should list available tools', async () => { const tools = await client.listTools(); // Check for tools directly in the response format expect(tools.tools.some(tool => tool.name === 'identity')).toBe(true); expect(tools.tools.some(tool => tool.name === 'upload')).toBe(true); expect(tools.tools.some(tool => tool.name === 'retrieve')).toBe(true); }); it('should get identity information', async () => { const response = await client.callTool({ name: 'identity', arguments: {}, // Send an empty object }); const responseContent = response.content as Array<{ type: string; text: string }>; expect(responseContent.length).toBeGreaterThan(0); const content = responseContent[0]; expect(content).toHaveProperty('text'); const responseData = JSON.parse(content.text); expect(responseData).toHaveProperty('id'); expect(responseData.id).toContain('did:key:'); }); it('should upload a file', async () => { // Read file content and convert to base64 string const fileBuffer = await fs.readFile(tempFilePath); const fileContent = fileBuffer.toString('base64'); // Upload file const uploadResponse = await client.callTool({ name: 'upload', arguments: { file: fileContent, // Send as base64 string name: 'test-file.txt', }, }); // Type assertion for upload response const uploadContent = ( uploadResponse.content as Array<{ type: string; text: string; error: boolean }> )[0]; expect(uploadContent).toHaveProperty('text'); // Parse upload response const uploadResult = JSON.parse(uploadContent.text); expect(uploadResult).toHaveProperty('root'); // The root can be either a string or an object with toString method expect(uploadResult.root).toBeDefined(); expect(uploadResult).toHaveProperty('url'); expect(uploadResult).toHaveProperty('files'); // Test that files is an object with at least one entry expect(typeof uploadResult.files).toBe('object'); expect(uploadResult.files).not.toBeNull(); // Get the first file entry (could be array or object format from dag-json) const fileEntries = Object.entries(uploadResult.files); expect(fileEntries.length).toBeGreaterThan(0); // Check the first file entry (could be in different formats depending on serialization) const firstFile = fileEntries[0]; expect(firstFile).toBeDefined(); }, 30_000); // Increase the timeout for upload test it('should retrieve a file', async () => { // Call retrieve tool const retrieveResponse = await client.callTool({ name: 'retrieve', arguments: { filepath: TEST_FILEPATH, }, }); // Type assertion for retrieve response const retrieveContent = (retrieveResponse.content as Array<{ type: string; text: string }>)[0]; expect(retrieveContent).toHaveProperty('text'); // Parse retrieve response const retrieveResult = JSON.parse(retrieveContent.text); expect(retrieveResult).toHaveProperty('data'); // MIME type may or may not be present depending on server configuration // so we don't assert on it to make the test more robust }, 30_000); // Increase timeout for retrieve test it('should handle invalid upload parameters', async () => { // Try uploading without required parameters try { await client.callTool({ name: 'upload', arguments: { // Missing required parameters }, }); // Should not reach here expect(true).toBe(false); } catch (error) { expect(error).toBeDefined(); } }); it('should handle invalid retrieve parameters', async () => { // Test with invalid CID format (missing filename) try { await client.callTool({ name: 'retrieve', arguments: { filepath: 'invalid-cid', // Missing the required filename }, }); // Should not reach here expect(true).toBe(false); } catch (error) { expect(error).toBeDefined(); } }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/storacha/mcp-storage-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server