test-mcp-simple.ts•9.05 kB
/**
* GoogleDocsMCP Simple Integration Test
* Tests platform OAuth token injection through direct tool simulation
* STEP 2 of Two-Step Testing Process
*/
// Platform OAuth token (from environment variable)
// Set this before running: export GOOGLE_OAUTH_TOKEN="your_token_here"
const ACCESS_TOKEN = process.env.GOOGLE_OAUTH_TOKEN || '';
if (!ACCESS_TOKEN) {
console.error('❌ ERROR: GOOGLE_OAUTH_TOKEN environment variable not set');
console.error('Usage: GOOGLE_OAUTH_TOKEN="your_token" npx tsx test-mcp-simple.ts');
process.exit(1);
}
// Test document ID (created in STEP 1)
const TEST_DOC_ID = "1EYHwxTzTFeg__ZRc8i9UPNAj79yCJ_hCKAsTYWQHZss";
import { google } from 'googleapis';
import { OAuth2Client } from 'google-auth-library';
// Platform OAuth Integration Pattern (same as in server.ts)
function createDocsClient(accessToken: string) {
const auth = new OAuth2Client();
auth.setCredentials({ access_token: accessToken });
return google.docs({ version: 'v1', auth });
}
function createDriveClient(accessToken: string) {
const auth = new OAuth2Client();
auth.setCredentials({ access_token: accessToken });
return google.drive({ version: 'v3', auth });
}
async function runTests() {
console.log('=================================');
console.log('GoogleDocsMCP Integration Test');
console.log('=================================\n');
console.log('Testing platform OAuth token injection pattern...\n');
let testsPassed = 0;
let testsFailed = 0;
try {
// Test 1: List Google Docs (simulating listGoogleDocs tool)
console.log('📋 Test 1: List Google Docs');
try {
const drive = createDriveClient(ACCESS_TOKEN);
const response = await drive.files.list({
q: "mimeType='application/vnd.google-apps.document'",
pageSize: 10,
fields: 'files(id, name, createdTime, modifiedTime)',
});
console.log(`✅ PASSED: Found ${response.data.files?.length || 0} documents`);
if (response.data.files && response.data.files.length > 0) {
response.data.files.forEach((file, idx) => {
console.log(` ${idx + 1}. "${file.name}" (${file.id})`);
});
}
testsPassed++;
} catch (error: any) {
console.log(`❌ FAILED: ${error.message}`);
testsFailed++;
}
console.log('');
// Test 2: Read Document (simulating readGoogleDoc tool)
console.log('📄 Test 2: Read Google Doc');
try {
const docs = createDocsClient(ACCESS_TOKEN);
const response = await docs.documents.get({
documentId: TEST_DOC_ID,
});
let textContent = '';
response.data.body?.content?.forEach(element => {
element.paragraph?.elements?.forEach(pe => {
textContent += pe.textRun?.content || '';
});
});
console.log(`✅ PASSED: Read document "${response.data.title}"`);
console.log(` Content length: ${textContent.length} characters`);
console.log(` Content preview: "${textContent.substring(0, 100).trim()}..."`);
testsPassed++;
} catch (error: any) {
console.log(`❌ FAILED: ${error.message}`);
testsFailed++;
}
console.log('');
// Test 3: Append Text (simulating appendToGoogleDoc tool)
console.log('✍️ Test 3: Append Text to Document');
try {
const docs = createDocsClient(ACCESS_TOKEN);
// Get current end index
const docInfo = await docs.documents.get({
documentId: TEST_DOC_ID,
fields: 'body(content(endIndex))'
});
let endIndex = 1;
if (docInfo.data.body?.content) {
const lastElement = docInfo.data.body.content[docInfo.data.body.content.length - 1];
if (lastElement?.endIndex) {
endIndex = lastElement.endIndex - 1;
}
}
const testText = '\n\n=== MCP Integration Test ===\nThis text was added via MCP platform OAuth token injection.\nTimestamp: ' + new Date().toISOString() + '\n';
await docs.documents.batchUpdate({
documentId: TEST_DOC_ID,
requestBody: {
requests: [{
insertText: {
location: { index: endIndex },
text: testText
}
}]
}
});
console.log(`✅ PASSED: Appended ${testText.length} characters at index ${endIndex}`);
testsPassed++;
} catch (error: any) {
console.log(`❌ FAILED: ${error.message}`);
testsFailed++;
}
console.log('');
// Test 4: Create New Document (simulating createDocument tool)
console.log('📝 Test 4: Create New Document');
try {
const docs = createDocsClient(ACCESS_TOKEN);
const timestamp = new Date().toISOString();
const title = `MCP Test Doc - ${timestamp}`;
const response = await docs.documents.create({
requestBody: {
title: title
}
});
console.log(`✅ PASSED: Created document "${response.data.title}"`);
console.log(` Document ID: ${response.data.documentId}`);
console.log(` URL: https://docs.google.com/document/d/${response.data.documentId}/edit`);
testsPassed++;
// Clean up: Delete the test document
try {
const drive = createDriveClient(ACCESS_TOKEN);
await drive.files.delete({ fileId: response.data.documentId! });
console.log(` ♻️ Cleaned up: Deleted test document`);
} catch (cleanupError) {
console.log(` ⚠️ Cleanup warning: Could not delete test document`);
}
} catch (error: any) {
console.log(`❌ FAILED: ${error.message}`);
testsFailed++;
}
console.log('');
// Test 5: Apply Text Formatting (simulating applyTextStyle tool)
console.log('🎨 Test 5: Apply Text Formatting');
try {
const docs = createDocsClient(ACCESS_TOKEN);
// Find the test text we added
const docContent = await docs.documents.get({ documentId: TEST_DOC_ID });
let fullText = '';
let segments: Array<{ start: number; end: number; text: string }> = [];
docContent.data.body?.content?.forEach(element => {
element.paragraph?.elements?.forEach(pe => {
if (pe.textRun?.content && pe.startIndex && pe.endIndex) {
fullText += pe.textRun.content;
segments.push({
text: pe.textRun.content,
start: pe.startIndex,
end: pe.endIndex
});
}
});
});
// Find "MCP Integration Test" text
const searchText = "MCP Integration Test";
const textIndex = fullText.indexOf(searchText);
if (textIndex >= 0) {
let startIndex = -1, endIndex = -1;
let currentPos = 0;
for (const seg of segments) {
const segTextLength = seg.text.length;
if (textIndex >= currentPos && textIndex < currentPos + segTextLength) {
startIndex = seg.start + (textIndex - currentPos);
endIndex = startIndex + searchText.length;
break;
}
currentPos += segTextLength;
}
if (startIndex >= 0 && endIndex > startIndex) {
await docs.documents.batchUpdate({
documentId: TEST_DOC_ID,
requestBody: {
requests: [{
updateTextStyle: {
range: { startIndex, endIndex },
textStyle: {
bold: true,
foregroundColor: {
color: {
rgbColor: { red: 1, green: 0, blue: 0 }
}
}
},
fields: 'bold,foregroundColor'
}
}]
}
});
console.log(`✅ PASSED: Applied bold + red color to text at indices ${startIndex}-${endIndex}`);
testsPassed++;
} else {
console.log(`⚠️ SKIPPED: Could not map text to document indices`);
}
} else {
console.log(`⚠️ SKIPPED: Test text not found in document`);
}
} catch (error: any) {
console.log(`❌ FAILED: ${error.message}`);
testsFailed++;
}
console.log('');
// Summary
console.log('=================================');
console.log('Test Summary');
console.log('=================================');
console.log(`✅ Tests Passed: ${testsPassed}`);
console.log(`❌ Tests Failed: ${testsFailed}`);
console.log(`📊 Success Rate: ${((testsPassed / (testsPassed + testsFailed)) * 100).toFixed(1)}%`);
console.log('=================================\n');
if (testsFailed === 0) {
console.log('🎉 All tests passed! GoogleDocsMCP is ready for platform integration.\n');
process.exit(0);
} else {
console.log('⚠️ Some tests failed. Review errors above.\n');
process.exit(1);
}
} catch (error: any) {
console.error('💥 Critical error during testing:', error);
process.exit(1);
}
}
// Run tests
runTests().catch(console.error);