Files
gh-jeremylongshore-claude-c…/commands/firestore-setup.md
2025-11-29 18:52:57 +08:00

14 KiB

name, description, model
name description model
firestore-setup Initialize Firebase Admin SDK, configure Firestore, and setup A2A/MCP integration sonnet

Firestore Setup Command

Initialize Firebase Admin SDK in your project with support for:

  • Basic Firestore operations (CRUD, queries)
  • A2A (Agent-to-Agent) framework integration
  • MCP server communication patterns
  • Cloud Run service integration
  • Service account authentication

Your Mission

Set up Firebase Admin SDK with proper configuration for both regular users and AI agents. Guide the user through:

  1. Environment detection - Check if Firebase is already configured
  2. Dependency installation - Install firebase-admin package
  3. Credential setup - Configure service account authentication
  4. Firestore initialization - Initialize and test connection
  5. A2A/MCP setup (optional) - Configure for agent communication
  6. Security rules (optional) - Deploy initial security rules

Step-by-Step Workflow

Step 1: Check Existing Setup

First, check if Firebase is already configured:

# Check if firebase-admin is installed
npm list firebase-admin

# Check for existing Firebase initialization
grep -r "firebase-admin" .

# Check for service account credentials
ls -la *.json | grep -i firebase

If Firebase is already set up, ask the user if they want to reconfigure.

Step 2: Install Dependencies

# Install firebase-admin
npm install firebase-admin

# For A2A/MCP integration, also install:
npm install @google-cloud/firestore
npm install dotenv  # For environment variables

Step 3: Get Service Account Credentials

Ask the user:

Option A: Download from Firebase Console

1. Go to https://console.firebase.google.com
2. Select your project
3. Settings (gear icon) → Project Settings → Service Accounts
4. Click "Generate new private key"
5. Save JSON file to your project (e.g., serviceAccountKey.json)

Option B: Use existing GCP credentials

# If using Google Cloud SDK
gcloud auth application-default login

Option C: Environment variable (production)

# Set environment variable
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/serviceAccountKey.json"

Step 4: Create Firebase Initialization File

Create src/firebase.js (or src/firebase.ts for TypeScript):

const admin = require('firebase-admin');

// Initialize Firebase Admin SDK
if (!admin.apps.length) {
  // Option 1: Using service account key file
  const serviceAccount = require('../serviceAccountKey.json');

  admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: `https://${serviceAccount.project_id}.firebaseio.com`
  });

  // Option 2: Using environment variable (recommended for production)
  // admin.initializeApp({
  //   credential: admin.credential.applicationDefault(),
  //   projectId: process.env.FIREBASE_PROJECT_ID
  // });
}

const db = admin.firestore();

// Export for use in other files
module.exports = { admin, db };

For TypeScript:

import * as admin from 'firebase-admin';

if (!admin.apps.length) {
  const serviceAccount = require('../serviceAccountKey.json');

  admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: `https://${serviceAccount.project_id}.firebaseio.com`
  });
}

export const db = admin.firestore();
export { admin };

Step 5: Test Connection

Create a test script to verify Firestore works:

const { db } = require('./src/firebase');

async function testFirestore() {
  try {
    // Test write
    const testRef = await db.collection('_test').add({
      message: 'Firebase connected successfully!',
      timestamp: admin.firestore.FieldValue.serverTimestamp()
    });

    console.log('✅ Write successful. Document ID:', testRef.id);

    // Test read
    const doc = await testRef.get();
    console.log('✅ Read successful. Data:', doc.data());

    // Clean up test document
    await testRef.delete();
    console.log('✅ Delete successful');

    console.log('\n🎉 Firebase is configured correctly!');
  } catch (error) {
    console.error('❌ Error:', error.message);
    process.exit(1);
  }
}

testFirestore();

Run the test:

node test-firestore.js

Step 6: A2A/MCP Setup (Optional)

If the user needs A2A or MCP integration, create additional configuration:

A. Create A2A configuration file (src/a2a-config.js):

const { db } = require('./firebase');

// A2A Framework Configuration
const A2A_CONFIG = {
  collections: {
    sessions: 'agent_sessions',
    memory: 'agent_memory',
    tasks: 'a2a_tasks',
    messages: 'a2a_messages',
    logs: 'agent_logs'
  },

  serviceAccounts: [
    'mcp-server@project-id.iam.gserviceaccount.com',
    'agent-engine@project-id.iam.gserviceaccount.com'
  ],

  sessionTTL: 3600, // 1 hour in seconds
  messageTTL: 86400, // 24 hours

  rateLimits: {
    maxRequestsPerMinute: 100,
    maxConcurrentSessions: 50
  }
};

// Initialize A2A collections
async function initializeA2ACollections() {
  const collections = Object.values(A2A_CONFIG.collections);

  for (const collection of collections) {
    const ref = db.collection(collection);

    // Create initial document to establish collection
    await ref.doc('_init').set({
      initialized: true,
      timestamp: new Date()
    });

    console.log(`✅ Initialized collection: ${collection}`);
  }
}

module.exports = { A2A_CONFIG, initializeA2ACollections };

B. Create MCP service integration (src/mcp-service.js):

const { db } = require('./firebase');
const { A2A_CONFIG } = require('./a2a-config');

class MCPService {
  constructor(serviceAccountEmail) {
    this.serviceAccountEmail = serviceAccountEmail;
    this.db = db;
  }

  // Create a new agent session
  async createSession(sessionData) {
    const sessionRef = this.db.collection(A2A_CONFIG.collections.sessions).doc();

    await sessionRef.set({
      ...sessionData,
      agentId: this.serviceAccountEmail,
      status: 'active',
      createdAt: admin.firestore.FieldValue.serverTimestamp(),
      expiresAt: new Date(Date.now() + A2A_CONFIG.sessionTTL * 1000)
    });

    return sessionRef.id;
  }

  // Store agent memory/context
  async storeContext(sessionId, contextData) {
    const contextRef = this.db
      .collection(A2A_CONFIG.collections.memory)
      .doc(this.serviceAccountEmail)
      .collection('contexts')
      .doc(sessionId);

    await contextRef.set({
      ...contextData,
      agentId: this.serviceAccountEmail,
      sessionId,
      timestamp: admin.firestore.FieldValue.serverTimestamp()
    });
  }

  // Send message to another agent
  async sendMessage(toAgent, payload) {
    await this.db.collection(A2A_CONFIG.collections.messages).add({
      from: this.serviceAccountEmail,
      to: toAgent,
      payload,
      timestamp: admin.firestore.FieldValue.serverTimestamp(),
      status: 'pending'
    });
  }

  // Receive messages for this agent
  async receiveMessages() {
    const snapshot = await this.db
      .collection(A2A_CONFIG.collections.messages)
      .where('to', '==', this.serviceAccountEmail)
      .where('status', '==', 'pending')
      .orderBy('timestamp', 'asc')
      .get();

    const messages = [];
    const batch = this.db.batch();

    snapshot.forEach(doc => {
      messages.push({ id: doc.id, ...doc.data() });
      // Mark as processed
      batch.update(doc.ref, { status: 'processed' });
    });

    await batch.commit();
    return messages;
  }

  // Log agent activity
  async logActivity(activity, level = 'info') {
    await this.db.collection(A2A_CONFIG.collections.logs).add({
      agentId: this.serviceAccountEmail,
      activity,
      level,
      timestamp: admin.firestore.FieldValue.serverTimestamp()
    });
  }
}

module.exports = { MCPService };

C. Create Cloud Run service integration (src/cloudrun-service.js):

const { db } = require('./firebase');

class CloudRunService {
  constructor() {
    this.db = db;
  }

  // Log API requests from Cloud Run
  async logRequest(endpoint, method, userId, metadata = {}) {
    await this.db.collection('api_requests').add({
      endpoint,
      method,
      userId,
      metadata,
      timestamp: admin.firestore.FieldValue.serverTimestamp()
    });
  }

  // Store API response
  async storeResponse(requestId, responseData) {
    await this.db.collection('api_responses').doc(requestId).set({
      ...responseData,
      timestamp: admin.firestore.FieldValue.serverTimestamp()
    });
  }

  // Get user data for Cloud Run service
  async getUserData(userId) {
    const doc = await this.db.collection('users').doc(userId).get();
    if (!doc.exists) {
      throw new Error('User not found');
    }
    return doc.data();
  }
}

module.exports = { CloudRunService };

Step 7: Setup Environment Variables

Create .env file:

# Firebase Configuration
GOOGLE_APPLICATION_CREDENTIALS=./serviceAccountKey.json
FIREBASE_PROJECT_ID=your-project-id

# A2A Configuration (if applicable)
MCP_SERVICE_ACCOUNT_EMAIL=mcp-server@project-id.iam.gserviceaccount.com
AGENT_ENGINE_SERVICE_ACCOUNT=agent-engine@project-id.iam.gserviceaccount.com

# Cloud Run Configuration (if applicable)
CLOUD_RUN_SERVICE_URL=https://your-service-abc123-uc.a.run.app

Add to .gitignore:

serviceAccountKey.json
.env

Step 8: Deploy Security Rules (Optional)

Ask if the user wants to deploy initial security rules:

# Install Firebase CLI
npm install -g firebase-tools

# Login
firebase login

# Initialize Firestore rules
firebase init firestore

Then use the firestore-security-agent to generate appropriate rules based on their use case.

Step 9: Create Example Usage File

Create examples/firestore-usage.js:

const { db, admin } = require('../src/firebase');

// Example 1: Basic CRUD
async function basicCRUD() {
  // Create
  const docRef = await db.collection('users').add({
    name: 'John Doe',
    email: '[email protected]',
    createdAt: admin.firestore.FieldValue.serverTimestamp()
  });

  // Read
  const doc = await docRef.get();
  console.log('User data:', doc.data());

  // Update
  await docRef.update({
    name: 'John Updated',
    updatedAt: admin.firestore.FieldValue.serverTimestamp()
  });

  // Delete
  await docRef.delete();
}

// Example 2: Queries
async function queryExamples() {
  // Simple query
  const activeUsers = await db.collection('users')
    .where('status', '==', 'active')
    .limit(10)
    .get();

  activeUsers.forEach(doc => {
    console.log(doc.id, doc.data());
  });

  // Complex query
  const recentOrders = await db.collection('orders')
    .where('userId', '==', 'user123')
    .where('status', '==', 'pending')
    .orderBy('createdAt', 'desc')
    .limit(5)
    .get();
}

// Example 3: Batch operations
async function batchOperations() {
  const batch = db.batch();

  // Add multiple documents
  for (let i = 0; i < 10; i++) {
    const ref = db.collection('items').doc();
    batch.set(ref, {
      name: `Item ${i}`,
      createdAt: admin.firestore.FieldValue.serverTimestamp()
    });
  }

  await batch.commit();
  console.log('Batch write completed');
}

// Example 4: A2A usage (if configured)
async function a2aExample() {
  const { MCPService } = require('../src/mcp-service');
  const mcp = new MCPService('mcp-server@project.iam.gserviceaccount.com');

  // Create session
  const sessionId = await mcp.createSession({
    task: 'process_user_data',
    priority: 'high'
  });

  // Store context
  await mcp.storeContext(sessionId, {
    userId: 'user123',
    action: 'data_processing'
  });

  // Send message to another agent
  await mcp.sendMessage(
    'agent-engine@project.iam.gserviceaccount.com',
    { action: 'analyze', data: { userId: 'user123' } }
  );

  // Log activity
  await mcp.logActivity('Processed user data', 'info');
}

module.exports = { basicCRUD, queryExamples, batchOperations, a2aExample };

Post-Setup Checklist

Verify the following after setup:

  • Firebase Admin SDK installed
  • Service account credentials configured
  • .gitignore includes serviceAccountKey.json and .env
  • Connection test passes
  • Example usage file works
  • A2A collections initialized (if applicable)
  • Security rules deployed (if applicable)
  • Environment variables set
  • Documentation updated

Next Steps

Tell the user:

  1. Test the setup - Run node test-firestore.js
  2. Read the examples - Check examples/firestore-usage.js
  3. Deploy security rules - Use /firestore-security-agent to generate rules
  4. Start building - Use /firebase-operations-agent for CRUD operations

Common Issues

Issue 1: "Permission denied" errors

  • Check service account has Firestore permissions
  • Verify security rules allow the operation
  • Ensure GOOGLE_APPLICATION_CREDENTIALS is set correctly

Issue 2: "Firebase app already initialized"

  • This is normal - only initialize once
  • Check if Firebase is initialized in multiple files

Issue 3: "Cannot find module 'firebase-admin'"

  • Run npm install firebase-admin
  • Check package.json includes firebase-admin

Issue 4: A2A collections not accessible

  • Verify service account email is whitelisted in security rules
  • Check firestore.rules includes A2A patterns
  • Test with Firebase Emulator first

Security Reminders

  1. Never commit serviceAccountKey.json to version control
  2. Use environment variables in production
  3. Whitelist service accounts in security rules
  4. Rotate credentials regularly (every 90 days recommended)
  5. Monitor usage with Firebase console
  6. Set up billing alerts to avoid surprises

Congratulations! Your Firestore setup is complete! 🎉