firestore-mcp-readonly 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +146 -0
  3. package/dist/config.d.ts +11 -0
  4. package/dist/config.js +37 -0
  5. package/dist/config.js.map +1 -0
  6. package/dist/db.d.ts +4 -0
  7. package/dist/db.js +49 -0
  8. package/dist/db.js.map +1 -0
  9. package/dist/errors.d.ts +9 -0
  10. package/dist/errors.js +62 -0
  11. package/dist/errors.js.map +1 -0
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.js +60 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/limiter.d.ts +12 -0
  16. package/dist/limiter.js +30 -0
  17. package/dist/limiter.js.map +1 -0
  18. package/dist/serializer.d.ts +18 -0
  19. package/dist/serializer.js +39 -0
  20. package/dist/serializer.js.map +1 -0
  21. package/dist/tools/collection-group-query.d.ts +2 -0
  22. package/dist/tools/collection-group-query.js +80 -0
  23. package/dist/tools/collection-group-query.js.map +1 -0
  24. package/dist/tools/count-documents.d.ts +2 -0
  25. package/dist/tools/count-documents.js +54 -0
  26. package/dist/tools/count-documents.js.map +1 -0
  27. package/dist/tools/dump-database.d.ts +3 -0
  28. package/dist/tools/dump-database.js +89 -0
  29. package/dist/tools/dump-database.js.map +1 -0
  30. package/dist/tools/dump-node.d.ts +3 -0
  31. package/dist/tools/dump-node.js +107 -0
  32. package/dist/tools/dump-node.js.map +1 -0
  33. package/dist/tools/get-collection.d.ts +3 -0
  34. package/dist/tools/get-collection.js +53 -0
  35. package/dist/tools/get-collection.js.map +1 -0
  36. package/dist/tools/get-document.d.ts +2 -0
  37. package/dist/tools/get-document.js +52 -0
  38. package/dist/tools/get-document.js.map +1 -0
  39. package/dist/tools/get-server-info.d.ts +3 -0
  40. package/dist/tools/get-server-info.js +31 -0
  41. package/dist/tools/get-server-info.js.map +1 -0
  42. package/dist/tools/list-indexes.d.ts +3 -0
  43. package/dist/tools/list-indexes.js +92 -0
  44. package/dist/tools/list-indexes.js.map +1 -0
  45. package/dist/tools/list-subcollections.d.ts +2 -0
  46. package/dist/tools/list-subcollections.js +46 -0
  47. package/dist/tools/list-subcollections.js.map +1 -0
  48. package/dist/tools/query-collection.d.ts +2 -0
  49. package/dist/tools/query-collection.js +108 -0
  50. package/dist/tools/query-collection.js.map +1 -0
  51. package/dist/tools/read-collection-ordered.d.ts +3 -0
  52. package/dist/tools/read-collection-ordered.js +135 -0
  53. package/dist/tools/read-collection-ordered.js.map +1 -0
  54. package/package.json +70 -0
@@ -0,0 +1,108 @@
1
+ import { z } from 'zod';
2
+ import { getDb } from '../db.js';
3
+ import { serializeDocument } from '../serializer.js';
4
+ import { formatFirestoreError } from '../errors.js';
5
+ const whereClause = z.object({
6
+ field: z.string().describe('Field name to filter on'),
7
+ op: z.enum(['==', '!=', '<', '<=', '>', '>=', 'array-contains', 'array-contains-any', 'in', 'not-in'])
8
+ .describe('Firestore comparison operator'),
9
+ value: z.union([
10
+ z.string(),
11
+ z.number(),
12
+ z.boolean(),
13
+ z.null(),
14
+ z.array(z.union([z.string(), z.number(), z.boolean(), z.null()])),
15
+ ]).describe('Value to compare against. Use array for "in", "not-in", "array-contains-any" operators.'),
16
+ });
17
+ const orderByClause = z.object({
18
+ field: z.string().describe('Field name to order by'),
19
+ direction: z.enum(['asc', 'desc']).default('asc').describe('Sort direction'),
20
+ });
21
+ export function registerQueryCollection(server) {
22
+ server.tool('firestore_query_collection', 'Query a Firestore collection with filters, ordering, and pagination. Supports all Firestore query operators. Note: complex queries may require composite indexes.', {
23
+ collectionPath: z.string().describe('Collection path, e.g. "users" or "tenants/t1/orders"'),
24
+ where: z.array(whereClause).optional()
25
+ .describe('Array of where filter clauses — all are ANDed together'),
26
+ orderBy: z.array(orderByClause).optional()
27
+ .describe('Array of orderBy clauses applied in order'),
28
+ limit: z.number().int().min(1).max(1000).optional().default(50)
29
+ .describe('Max documents to return (default: 50, max: 1000)'),
30
+ offset: z.number().int().min(0).optional().default(0)
31
+ .describe('Number of documents to skip (for offset-based pagination)'),
32
+ startAt: z.string().optional()
33
+ .describe('Document ID to start at (cursor-based pagination, inclusive)'),
34
+ startAfter: z.string().optional()
35
+ .describe('Document ID to start after (cursor-based pagination, exclusive)'),
36
+ endAt: z.string().optional()
37
+ .describe('Document ID to end at (inclusive)'),
38
+ endBefore: z.string().optional()
39
+ .describe('Document ID to end before (exclusive)'),
40
+ }, async ({ collectionPath, where: whereClauses, orderBy: orderByClauses, limit, offset, startAt, startAfter, endAt, endBefore }) => {
41
+ try {
42
+ const db = getDb();
43
+ let query = db.collection(collectionPath);
44
+ if (whereClauses) {
45
+ for (const clause of whereClauses) {
46
+ query = query.where(clause.field, clause.op, clause.value);
47
+ }
48
+ }
49
+ if (orderByClauses) {
50
+ for (const clause of orderByClauses) {
51
+ query = query.orderBy(clause.field, clause.direction);
52
+ }
53
+ }
54
+ if (startAt) {
55
+ const snap = await db.doc(`${collectionPath}/${startAt}`).get();
56
+ if (snap.exists)
57
+ query = query.startAt(snap);
58
+ }
59
+ if (startAfter) {
60
+ const snap = await db.doc(`${collectionPath}/${startAfter}`).get();
61
+ if (snap.exists)
62
+ query = query.startAfter(snap);
63
+ }
64
+ if (endAt) {
65
+ const snap = await db.doc(`${collectionPath}/${endAt}`).get();
66
+ if (snap.exists)
67
+ query = query.endAt(snap);
68
+ }
69
+ if (endBefore) {
70
+ const snap = await db.doc(`${collectionPath}/${endBefore}`).get();
71
+ if (snap.exists)
72
+ query = query.endBefore(snap);
73
+ }
74
+ if (offset) {
75
+ query = query.offset(offset);
76
+ }
77
+ query = query.limit(limit);
78
+ const snapshot = await query.get();
79
+ const documents = snapshot.docs.map(doc => serializeDocument(doc.id, doc.ref.path, doc.data()));
80
+ return {
81
+ content: [{
82
+ type: 'text',
83
+ text: JSON.stringify({
84
+ collectionPath,
85
+ count: documents.length,
86
+ query: {
87
+ filters: whereClauses?.length ?? 0,
88
+ orderBy: orderByClauses?.map(o => `${o.field} ${o.direction}`) ?? [],
89
+ limit,
90
+ offset,
91
+ },
92
+ documents,
93
+ }, null, 2),
94
+ }],
95
+ };
96
+ }
97
+ catch (error) {
98
+ return {
99
+ content: [{
100
+ type: 'text',
101
+ text: JSON.stringify(formatFirestoreError(error, 'firestore_query_collection'), null, 2),
102
+ }],
103
+ isError: true,
104
+ };
105
+ }
106
+ });
107
+ }
108
+ //# sourceMappingURL=query-collection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-collection.js","sourceRoot":"","sources":["../../src/tools/query-collection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { FirestoreConfig } from '../config.js';
3
+ export declare function registerReadCollectionOrdered(server: McpServer, config: FirestoreConfig): void;
@@ -0,0 +1,135 @@
1
+ import { z } from 'zod';
2
+ import { getDb } from '../db.js';
3
+ import { serializeDocument } from '../serializer.js';
4
+ import { DumpLimiter, LimitExceededError } from '../limiter.js';
5
+ import { formatFirestoreError } from '../errors.js';
6
+ const orderByClause = z.object({
7
+ field: z.string().describe('Field name to sort by'),
8
+ direction: z.enum(['asc', 'desc']).default('asc').describe('Sort direction'),
9
+ });
10
+ async function collectDocuments(collectionPath, depth, limiter, maxDocsPerCollection, docs) {
11
+ limiter.checkDepth(depth);
12
+ const db = getDb();
13
+ const snapshot = await db.collection(collectionPath).limit(maxDocsPerCollection).get();
14
+ limiter.addDocs(snapshot.docs.length);
15
+ for (const doc of snapshot.docs) {
16
+ docs.push(serializeDocument(doc.id, doc.ref.path, doc.data()));
17
+ const subcollections = await doc.ref.listCollections();
18
+ for (const sub of subcollections) {
19
+ await collectDocuments(sub.path, depth + 1, limiter, maxDocsPerCollection, docs);
20
+ }
21
+ }
22
+ }
23
+ function getSortValue(doc, field) {
24
+ const val = doc[field];
25
+ if (val === undefined || val === null)
26
+ return undefined;
27
+ if (typeof val === 'object' && val !== null && '_type' in val) {
28
+ const typed = val;
29
+ if (typed._type === 'timestamp')
30
+ return typed.value;
31
+ if (typed._type === 'geopoint')
32
+ return typed.lat;
33
+ if (typed._type === 'reference')
34
+ return typed.path;
35
+ }
36
+ return val;
37
+ }
38
+ function compareValues(a, b, direction) {
39
+ const aUndef = a === undefined || a === null;
40
+ const bUndef = b === undefined || b === null;
41
+ if (aUndef && bUndef)
42
+ return 0;
43
+ if (aUndef)
44
+ return 1;
45
+ if (bUndef)
46
+ return -1;
47
+ let result = 0;
48
+ if (typeof a === 'number' && typeof b === 'number') {
49
+ result = a - b;
50
+ }
51
+ else {
52
+ result = String(a).localeCompare(String(b));
53
+ }
54
+ return direction === 'desc' ? -result : result;
55
+ }
56
+ export function registerReadCollectionOrdered(server, config) {
57
+ server.tool('firestore_read_collection_ordered', 'Recursively read all documents from a collection and its subcollections, returning a flat list sorted by one or more fields. Useful for getting an ordered view across an entire document hierarchy.', {
58
+ collectionPath: z.string().describe('Collection path, e.g. "users" or "tenants/t1/projects"'),
59
+ orderBy: z.array(orderByClause).min(1)
60
+ .describe('Fields to sort by, applied in order. First entry is primary sort, rest are tiebreakers.'),
61
+ limit: z.number().int().min(1).max(1000).optional().default(100)
62
+ .describe('Max documents to return after sorting (default: 100, max: 1000)'),
63
+ maxDepth: z.number().int().min(1).max(20).optional()
64
+ .describe('Override max recursion depth (default from server config)'),
65
+ maxDocs: z.number().int().min(1).max(10000).optional()
66
+ .describe('Override max total documents to read (default from server config)'),
67
+ }, async ({ collectionPath, orderBy: orderByClauses, limit, maxDepth, maxDocs }) => {
68
+ const limiter = new DumpLimiter(maxDocs ?? config.limits.maxTotalDumpDocs, maxDepth ?? config.limits.maxRecursionDepth);
69
+ try {
70
+ const segments = collectionPath.split('/').filter(Boolean);
71
+ if (segments.length === 0 || segments.length % 2 !== 1) {
72
+ return {
73
+ content: [{
74
+ type: 'text',
75
+ text: JSON.stringify({
76
+ error: `Invalid collection path "${collectionPath}": must have an odd number of segments. Got ${segments.length} segment(s).`,
77
+ }),
78
+ }],
79
+ isError: true,
80
+ };
81
+ }
82
+ const docs = [];
83
+ await collectDocuments(collectionPath, 0, limiter, config.limits.maxDocsPerCollection, docs);
84
+ docs.sort((a, b) => {
85
+ for (const clause of orderByClauses) {
86
+ const aVal = getSortValue(a, clause.field);
87
+ const bVal = getSortValue(b, clause.field);
88
+ const cmp = compareValues(aVal, bVal, clause.direction);
89
+ if (cmp !== 0)
90
+ return cmp;
91
+ }
92
+ return 0;
93
+ });
94
+ const limited = docs.slice(0, limit);
95
+ return {
96
+ content: [{
97
+ type: 'text',
98
+ text: JSON.stringify({
99
+ collectionPath,
100
+ orderBy: orderByClauses.map(o => `${o.field} ${o.direction}`),
101
+ totalDocsRead: limiter.docsProcessed,
102
+ count: limited.length,
103
+ truncatedByLimit: docs.length > limit,
104
+ limitReached: false,
105
+ documents: limited,
106
+ }, null, 2),
107
+ }],
108
+ };
109
+ }
110
+ catch (error) {
111
+ if (error instanceof LimitExceededError) {
112
+ return {
113
+ content: [{
114
+ type: 'text',
115
+ text: JSON.stringify({
116
+ collectionPath,
117
+ totalDocsRead: limiter.docsProcessed,
118
+ limitReached: true,
119
+ limitReason: error.message,
120
+ note: 'Partial data returned. Use a narrower path or increase limits.',
121
+ }, null, 2),
122
+ }],
123
+ };
124
+ }
125
+ return {
126
+ content: [{
127
+ type: 'text',
128
+ text: JSON.stringify(formatFirestoreError(error, 'firestore_read_collection_ordered'), null, 2),
129
+ }],
130
+ isError: true,
131
+ };
132
+ }
133
+ });
134
+ }
135
+ //# sourceMappingURL=read-collection-ordered.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-collection-ordered.js","sourceRoot":"","sources":["../../src/tools/read-collection-ordered.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "firestore-mcp-readonly",
3
+ "version": "0.1.1",
4
+ "description": "Read-only Firestore MCP server for AI agents — query, explore, and dump Firestore databases via Model Context Protocol",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "firestore-mcp-readonly": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsc --watch",
13
+ "start": "node dist/index.js",
14
+ "prepublishOnly": "npm run build",
15
+ "test": "cross-env NODE_OPTIONS=--experimental-vm-modules jest --passWithNoTests",
16
+ "lint": "eslint src/"
17
+ },
18
+ "dependencies": {
19
+ "@modelcontextprotocol/sdk": "^1.12.1",
20
+ "firebase-admin": "^13.10.0"
21
+ },
22
+ "devDependencies": {
23
+ "@types/jest": "^29.5.12",
24
+ "@types/node": "^22.0.0",
25
+ "cross-env": "^10.1.0",
26
+ "jest": "^29.7.0",
27
+ "ts-jest": "^29.3.0",
28
+ "typescript": "^5.7.0"
29
+ },
30
+ "engines": {
31
+ "node": ">=18.0.0"
32
+ },
33
+ "keywords": [
34
+ "mcp",
35
+ "mcp-server",
36
+ "firestore",
37
+ "firebase",
38
+ "google-cloud",
39
+ "google-cloud-firestore",
40
+ "gcp",
41
+ "database",
42
+ "nosql",
43
+ "readonly",
44
+ "model-context-protocol",
45
+ "ai-agent",
46
+ "ai-tools",
47
+ "claude",
48
+ "claude-mcp",
49
+ "cursor",
50
+ "ai"
51
+ ],
52
+ "author": "rilfi",
53
+ "license": "MIT",
54
+ "repository": {
55
+ "type": "git",
56
+ "url": "git+https://github.com/rilfi/firestore-mcp-readonly.git"
57
+ },
58
+ "homepage": "https://github.com/rilfi/firestore-mcp-readonly#readme",
59
+ "bugs": {
60
+ "url": "https://github.com/rilfi/firestore-mcp-readonly/issues"
61
+ },
62
+ "files": [
63
+ "dist/",
64
+ "README.md",
65
+ "LICENSE"
66
+ ],
67
+ "publishConfig": {
68
+ "access": "public"
69
+ }
70
+ }