/**
* Test client for MCP Quoting System
* Demonstrates how to call the coordinator and individual functions
*/
import { QuoteEvaluationResult } from './types';
const BASE_URL = 'http://localhost:3789';
// API Response types
interface ApiResponse<T = any> {
ok: boolean;
error?: string;
[key: string]: any;
}
interface HealthResponse extends ApiResponse {
status: string;
}
interface HistoricalQuotesResponse extends ApiResponse {
count: number;
quotes: any[];
}
interface EvaluationResponse extends ApiResponse {
result: QuoteEvaluationResult;
}
interface ReviewResponse extends ApiResponse {
review: string;
}
// Helper function for API calls
async function callAPI(endpoint: string, data?: any): Promise<any> {
const response = await fetch(`${BASE_URL}${endpoint}`, {
method: data ? 'POST' : 'GET',
headers: data ? { 'Content-Type': 'application/json' } : {},
body: data ? JSON.stringify(data) : undefined,
});
return response.json();
}
// Test cases
const testRFPs = [
{
name: 'Test 1: High Similarity (Should match Q-1001)',
rfp: {
rawText: 'We need 200 pcs of a 6061-T6 aluminum widget, CNC machined, anodize finish, tolerance +/-0.005, delivery by 2025-02-28. Contact: buyer@acme.com',
qty: 200,
contactEmail: 'buyer@acme.com',
customerName: 'Test Customer 1',
},
},
{
name: 'Test 2: Stainless Steel (Should match Q-0832 or Q-1567)',
rfp: {
rawText: '50 parts in 304 stainless steel, laser cut and welded, passivate finish. Tolerances +/-0.010. Rush delivery needed.',
qty: 50,
contactEmail: 'engineer@techcorp.com',
customerName: 'TechCorp',
},
},
{
name: 'Test 3: High Volume (Should match Q-0955)',
rfp: {
rawText: 'Bulk order: 750 aluminum brackets, CNC machined, powder coated black. Standard tolerances acceptable.',
qty: 750,
contactEmail: 'purchasing@buildtech.com',
customerName: 'BuildTech',
},
},
{
name: 'Test 4: New Material (Low confidence expected)',
rfp: {
rawText: 'We need 25 brass fittings, CNC turned and polished. Part number: BF-2025. Tolerance +/-0.002.',
qty: 25,
contactEmail: 'buyer@marineequip.com',
customerName: 'Marine Equipment',
partNumber: 'BF-2025',
},
},
{
name: 'Test 5: Minimal Information (Low confidence expected)',
rfp: {
rawText: 'Quote for 100 metal parts please',
qty: 100,
},
},
];
async function runTests() {
console.log('\n' + '='.repeat(70));
console.log('MCP QUOTING SYSTEM - TEST CLIENT');
console.log('='.repeat(70) + '\n');
// Check server health
console.log('Checking server health...');
try {
const health = await callAPI('/health') as HealthResponse;
if (!health.ok) {
console.error('❌ Server is not healthy!');
return;
}
console.log('✓ Server is healthy\n');
} catch (error) {
console.error('❌ Cannot connect to server. Is it running on port 3789?');
return;
}
// Check historical quotes
console.log('Loading historical quotes...');
const histResult = await callAPI('/mcp/utility/historicalQuotes') as HistoricalQuotesResponse;
console.log(`✓ Found ${histResult.count} historical quotes\n`);
// Run each test
for (let i = 0; i < testRFPs.length; i++) {
const test = testRFPs[i];
console.log('\n' + '-'.repeat(70));
console.log(`${test.name}`);
console.log('-'.repeat(70));
try {
// Call coordinator
console.log('\nCalling evaluateRfpAndDraftQuote...');
const result = await callAPI('/mcp/invoke/evaluateRfpAndDraftQuote', {
rfp: test.rfp,
}) as EvaluationResponse;
if (!result.ok) {
console.error('❌ Error:', result.error);
continue;
}
// Get formatted review
const reviewResult = await callAPI('/mcp/utility/formatReview', {
result: result.result,
}) as ReviewResponse;
if (reviewResult.ok) {
console.log(reviewResult.review);
}
// Summary
const { parsedRfp, matches, estimate, doc } = result.result;
console.log('\n📊 SUMMARY:');
console.log(` Material: ${parsedRfp.material}`);
console.log(` Processes: ${parsedRfp.processes?.join(', ') || 'none'}`);
console.log(` Similar quotes found: ${matches.length}`);
if (matches.length > 0) {
console.log(` Top match: ${matches[0].quote.id} (${(matches[0].score * 100).toFixed(1)}%)`);
}
console.log(` Total price: $${estimate.totalPrice.toFixed(2)}`);
console.log(` Lead time: ${estimate.leadDays} days`);
console.log(` Confidence: ${estimate.confidence.toUpperCase()}`);
console.log(` Quote ID: ${doc.quoteId}`);
} catch (error: any) {
console.error('❌ Test failed:', error.message);
}
// Pause between tests
await new Promise(resolve => setTimeout(resolve, 1000));
}
console.log('\n' + '='.repeat(70));
console.log('ALL TESTS COMPLETE');
console.log('='.repeat(70) + '\n');
}
// Run if executed directly
if (require.main === module) {
runTests().catch(console.error);
}
export { runTests, callAPI };