545 lines
14 KiB
Markdown
545 lines
14 KiB
Markdown
---
|
|
name: firestore-setup
|
|
description: Initialize Firebase Admin SDK, configure Firestore, and setup A2A/MCP integration
|
|
model: 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:
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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**
|
|
```bash
|
|
# If using Google Cloud SDK
|
|
gcloud auth application-default login
|
|
```
|
|
|
|
**Option C: Environment variable (production)**
|
|
```bash
|
|
# 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):
|
|
|
|
```javascript
|
|
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:
|
|
```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:
|
|
|
|
```javascript
|
|
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:
|
|
```bash
|
|
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`):
|
|
|
|
```javascript
|
|
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`):
|
|
|
|
```javascript
|
|
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`):
|
|
|
|
```javascript
|
|
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:
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
# 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`:
|
|
|
|
```javascript
|
|
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! 🎉
|