#!/usr/bin/env node
/**
* Simple test client for the MCP Datastore Server
* This sends MCP protocol messages to test the server functionality
*/
import { spawn } from 'child_process';
import { createInterface } from 'readline';
// Start the MCP server
const server = spawn('node', ['build/index.js'], {
stdio: ['pipe', 'pipe', 'inherit'],
env: {
...process.env,
GOOGLE_APPLICATION_CREDENTIALS: process.env.GOOGLE_APPLICATION_CREDENTIALS,
GOOGLE_CLOUD_PROJECT: process.env.GOOGLE_CLOUD_PROJECT
}
});
let requestId = 0;
const pendingRequests = new Map();
// Handle server output
const rl = createInterface({
input: server.stdout,
crlfDelay: Infinity
});
rl.on('line', (line) => {
try {
const response = JSON.parse(line);
console.log('š„ Server Response:', JSON.stringify(response, null, 2));
if (response.id && pendingRequests.has(response.id)) {
const resolve = pendingRequests.get(response.id);
pendingRequests.delete(response.id);
resolve(response);
}
} catch (e) {
console.log('š Server output:', line);
}
});
server.on('error', (error) => {
console.error('ā Server error:', error);
process.exit(1);
});
server.on('exit', (code) => {
console.log(`Server exited with code ${code}`);
process.exit(code);
});
// Send a JSON-RPC request
function sendRequest(method, params = {}) {
return new Promise((resolve) => {
const id = ++requestId;
const request = {
jsonrpc: '2.0',
id,
method,
params
};
console.log('\nš¤ Sending Request:', JSON.stringify(request, null, 2));
server.stdin.write(JSON.stringify(request) + '\n');
pendingRequests.set(id, resolve);
});
}
// Wait for a bit
const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms));
// Run tests
async function runTests() {
try {
console.log('š Starting MCP Datastore Server Tests\n');
// Wait for server to start
await wait(1000);
// 1. Initialize the connection
console.log('\n=== Test 1: Initialize ===');
await sendRequest('initialize', {
protocolVersion: '2024-11-05',
capabilities: {},
clientInfo: {
name: 'test-client',
version: '1.0.0'
}
});
await wait(500);
// 2. List available tools
console.log('\n=== Test 2: List Tools ===');
await sendRequest('tools/list');
await wait(500);
// 3. Insert a test entity
console.log('\n=== Test 3: Insert Entity ===');
const testData = {
name: 'Test User',
email: `test-${Date.now()}@example.com`,
age: 25,
createdAt: new Date().toISOString()
};
await sendRequest('tools/call', {
name: 'datastore_insert',
arguments: {
kind: 'TestUser',
data: testData
}
});
await wait(500);
// 4. Query entities
console.log('\n=== Test 4: Query Entities ===');
await sendRequest('tools/call', {
name: 'datastore_query',
arguments: {
kind: 'TestUser',
limit: 5
}
});
await wait(500);
// 5. Insert entity with specific ID
console.log('\n=== Test 5: Insert with ID ===');
const testId = `test-${Date.now()}`;
await sendRequest('tools/call', {
name: 'datastore_insert',
arguments: {
kind: 'TestUser',
keyId: testId,
data: {
name: 'User with ID',
email: `specific-${Date.now()}@example.com`,
age: 30
}
}
});
await wait(500);
// 6. Get entity by ID
console.log('\n=== Test 6: Get Entity by ID ===');
await sendRequest('tools/call', {
name: 'datastore_get',
arguments: {
kind: 'TestUser',
keyId: testId
}
});
await wait(500);
// 7. Update entity
console.log('\n=== Test 7: Update Entity ===');
await sendRequest('tools/call', {
name: 'datastore_update',
arguments: {
kind: 'TestUser',
keyId: testId,
data: {
name: 'Updated User',
email: `updated-${Date.now()}@example.com`,
age: 31,
updatedAt: new Date().toISOString()
}
}
});
await wait(500);
// 8. Query with filters
console.log('\n=== Test 8: Query with Filters ===');
await sendRequest('tools/call', {
name: 'datastore_query',
arguments: {
kind: 'TestUser',
filters: [
{
property: 'age',
operator: '>=',
value: 25
}
],
orderBy: [
{
property: 'age',
descending: false
}
],
limit: 10
}
});
await wait(500);
// 9. Delete entity
console.log('\n=== Test 9: Delete Entity ===');
await sendRequest('tools/call', {
name: 'datastore_delete',
arguments: {
kind: 'TestUser',
keyId: testId
}
});
await wait(500);
// 10. Verify deletion
console.log('\n=== Test 10: Verify Deletion ===');
await sendRequest('tools/call', {
name: 'datastore_get',
arguments: {
kind: 'TestUser',
keyId: testId
}
});
await wait(500);
console.log('\nā
All tests completed!');
console.log('š Check your Datastore console to see the TestUser entities');
} catch (error) {
console.error('ā Test failed:', error);
} finally {
// Clean up
await wait(1000);
server.kill();
process.exit(0);
}
}
// Start tests
runTests();