Manages Firebase/Firestore operations including CRUD, queries, batch processing, A2A agent communication, MCP server integration, and Cloud Run service coordination. Activates when you request "firestore operations", "create firestore document", "...
Limited to specific tools
Additional assets for this skill
This skill is limited to using the following tools:
scripts/setup-firestore.shdescription: Manages Firebase/Firestore operations including CRUD, queries, batch processing, A2A agent communication, MCP server integration, and Cloud Run service coordination. Activates when you request "firestore operations", "create firestore document", "... allowed-tools:
This skill manages Firebase/Firestore operations for both regular web/mobile applications and AI agent-to-agent (A2A) frameworks. It handles:
This skill activates when users mention:
For basic users:
For A2A/MCP users:
Example setup:
# Basic setup
npm install firebase-admin
# A2A/MCP setup
npm install firebase-admin @google-cloud/firestore dotenv
# Set credentials
export GOOGLE_APPLICATION_CREDENTIALS="./serviceAccountKey.json"
# Run setup command
/firestore-setup
For standard database operations:
Create documents:
const { db, admin } = require('./src/firebase');
// Single document
await db.collection('users').add({
name: 'John Doe',
email: '[email protected]',
createdAt: admin.firestore.FieldValue.serverTimestamp()
});
// With custom ID
await db.collection('users').doc('user123').set({
name: 'Jane Doe',
email: '[email protected]'
});
Read documents:
// Single document
const doc = await db.collection('users').doc('user123').get();
const userData = doc.data();
// Query
const snapshot = await db.collection('users')
.where('status', '==', 'active')
.orderBy('createdAt', 'desc')
.limit(10)
.get();
snapshot.forEach(doc => console.log(doc.data()));
Update documents:
// Partial update
await db.collection('users').doc('user123').update({
status: 'active',
updatedAt: admin.firestore.FieldValue.serverTimestamp()
});
// Increment counter
await db.collection('stats').doc('views').update({
count: admin.firestore.FieldValue.increment(1)
});
Delete documents:
// Single delete
await db.collection('users').doc('user123').delete();
// Batch delete
const batch = db.batch();
const docs = await db.collection('temp').limit(500).get();
docs.forEach(doc => batch.delete(doc.ref));
await batch.commit();
For agent-to-agent communication patterns:
1. Create Agent Session:
const { MCPService } = require('./src/mcp-service');
const mcp = new MCPService('mcp-server@project.iam.gserviceaccount.com');
// Create session for agent workflow
const sessionId = await mcp.createSession({
task: 'process_user_data',
priority: 'high',
metadata: { userId: 'user123' }
});
console.log(`Session created: ${sessionId}`);
2. Store Agent Context:
// Store agent memory/context in Firestore
await mcp.storeContext(sessionId, {
conversation: [...messages],
userPreferences: { theme: 'dark' },
currentStep: 'data_validation'
});
// Retrieve context later
const context = await db
.collection('agent_memory')
.doc('mcp-server@project.iam.gserviceaccount.com')
.collection('contexts')
.doc(sessionId)
.get();
3. Agent-to-Agent Messaging:
// Send message from one agent to another
await mcp.sendMessage(
'agent-engine@project.iam.gserviceaccount.com',
{
action: 'analyze_data',
data: { userId: 'user123', fields: ['name', 'email'] }
}
);
// Receive messages (in receiving agent)
const messages = await mcp.receiveMessages();
messages.forEach(msg => {
console.log(`From: ${msg.from}, Payload:`, msg.payload);
});
4. Task Queue Management:
// Create task for another agent
await db.collection('a2a_tasks').add({
taskType: 'data_processing',
assignedTo: 'worker-agent@project.iam.gserviceaccount.com',
status: 'pending',
priority: 1,
payload: { userId: 'user123' },
createdAt: admin.firestore.FieldValue.serverTimestamp()
});
// Agent claims and processes task
const taskQuery = await db.collection('a2a_tasks')
.where('assignedTo', '==', 'worker-agent@project.iam.gserviceaccount.com')
.where('status', '==', 'pending')
.orderBy('priority', 'asc')
.limit(1)
.get();
if (!taskQuery.empty) {
const task = taskQuery.docs[0];
await task.ref.update({ status: 'in_progress' });
// Process task...
await task.ref.update({ status: 'completed' });
}
5. Agent Activity Logging:
// Log agent activities for audit trail
await mcp.logActivity({
action: 'processed_data',
userId: 'user123',
duration: 1500, // ms
result: 'success'
}, 'info');
For Cloud Run services accessing Firestore:
Setup Cloud Run service class:
const { CloudRunService } = require('./src/cloudrun-service');
const cloudrun = new CloudRunService();
// In your Cloud Run endpoint
app.post('/api/users/:userId/data', async (req, res) => {
const { userId } = req.params;
try {
// Log request
await cloudrun.logRequest('/api/users/data', 'POST', userId);
// Get user data from Firestore
const userData = await cloudrun.getUserData(userId);
// Store response
await cloudrun.storeResponse(req.id, {
userId,
data: userData,
status: 'success'
});
res.json({ success: true, data: userData });
} catch (error) {
await cloudrun.storeResponse(req.id, {
userId,
error: error.message,
status: 'error'
});
res.status(500).json({ error: error.message });
}
});
Generate and deploy security rules for both users and agents:
For basic users:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
}
}
For A2A/MCP (service accounts):
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
function isServiceAccount() {
return request.auth.token.email.matches('.*@.*\\.iam\\.gserviceaccount\\.com$');
}
function isAuthorizedAgent() {
return isServiceAccount() && request.auth.token.email in [
'mcp-server@project-id.iam.gserviceaccount.com',
'agent-engine@project-id.iam.gserviceaccount.com'
];
}
// Agent sessions
match /agent_sessions/{sessionId} {
allow read, write: if isAuthorizedAgent();
}
// Agent memory
match /agent_memory/{agentId}/{document=**} {
allow read, write: if isAuthorizedAgent();
}
// A2A messages
match /a2a_messages/{messageId} {
allow create: if isAuthorizedAgent();
allow read: if isAuthorizedAgent() &&
(resource.data.from == request.auth.token.email ||
resource.data.to == request.auth.token.email);
}
}
}
Deploy rules:
firebase deploy --only firestore:rules
// Coordinator agent creates workflow
const workflowId = await db.collection('workflows').add({
name: 'user_data_processing',
steps: [
{ agent: 'validator@project.iam.gserviceaccount.com', status: 'pending' },
{ agent: 'processor@project.iam.gserviceaccount.com', status: 'pending' },
{ agent: 'notifier@project.iam.gserviceaccount.com', status: 'pending' }
],
createdAt: admin.firestore.FieldValue.serverTimestamp()
});
// Each agent listens for their step
const unsubscribe = db.collection('workflows')
.doc(workflowId)
.onSnapshot(async (doc) => {
const workflow = doc.data();
const myStep = workflow.steps.find(s => s.agent === myEmail && s.status === 'pending');
if (myStep) {
// Process step
await processStep(myStep);
// Mark complete and notify next agent
myStep.status = 'completed';
await doc.ref.update({ steps: workflow.steps });
}
});
// Agent 1 stores context
await db.collection('shared_context').doc('task_abc').set({
sharedBy: 'agent1@project.iam.gserviceaccount.com',
sharedWith: ['agent2@project.iam.gserviceaccount.com'],
context: {
userId: 'user123',
analysis: { sentiment: 'positive', score: 0.85 }
},
expiresAt: new Date(Date.now() + 3600000) // 1 hour
});
// Agent 2 retrieves context
const contextDoc = await db.collection('shared_context').doc('task_abc').get();
if (contextDoc.exists && contextDoc.data().sharedWith.includes(myEmail)) {
const context = contextDoc.data().context;
// Use context...
}
// Check and enforce rate limits
const rateLimitRef = db.collection('rate_limits').doc(agentEmail);
const rateLimitDoc = await rateLimitRef.get();
if (rateLimitDoc.exists) {
const { count, resetAt } = rateLimitDoc.data();
if (Date.now() < resetAt && count >= 100) {
throw new Error('Rate limit exceeded');
}
if (Date.now() >= resetAt) {
// Reset counter
await rateLimitRef.set({
count: 1,
resetAt: Date.now() + 60000 // 1 minute
});
} else {
// Increment counter
await rateLimitRef.update({
count: admin.firestore.FieldValue.increment(1)
});
}
} else {
// First request
await rateLimitRef.set({
count: 1,
resetAt: Date.now() + 60000
});
}
Firestore costs:
Reduce costs:
See examples/firestore-usage.js for complete code examples covering:
This skill provides comprehensive Firestore operations for:
Use /firestore-setup to initialize, then leverage the agents and commands for specific operations!