assay-mcp-server 1.0.0

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 (67) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +421 -0
  3. package/dist/firebase.d.ts +53 -0
  4. package/dist/firebase.d.ts.map +1 -0
  5. package/dist/firebase.js +123 -0
  6. package/dist/firebase.js.map +1 -0
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +380 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/tools/askQuestion.d.ts +9 -0
  12. package/dist/tools/askQuestion.d.ts.map +1 -0
  13. package/dist/tools/askQuestion.js +27 -0
  14. package/dist/tools/askQuestion.js.map +1 -0
  15. package/dist/tools/browseAllDocuments.d.ts +17 -0
  16. package/dist/tools/browseAllDocuments.d.ts.map +1 -0
  17. package/dist/tools/browseAllDocuments.js +44 -0
  18. package/dist/tools/browseAllDocuments.js.map +1 -0
  19. package/dist/tools/browseThemes.d.ts +19 -0
  20. package/dist/tools/browseThemes.d.ts.map +1 -0
  21. package/dist/tools/browseThemes.js +20 -0
  22. package/dist/tools/browseThemes.js.map +1 -0
  23. package/dist/tools/compareDocuments.d.ts +9 -0
  24. package/dist/tools/compareDocuments.d.ts.map +1 -0
  25. package/dist/tools/compareDocuments.js +52 -0
  26. package/dist/tools/compareDocuments.js.map +1 -0
  27. package/dist/tools/getDocumentSummary.d.ts +12 -0
  28. package/dist/tools/getDocumentSummary.d.ts.map +1 -0
  29. package/dist/tools/getDocumentSummary.js +29 -0
  30. package/dist/tools/getDocumentSummary.js.map +1 -0
  31. package/dist/tools/getLibraryInsight.d.ts +7 -0
  32. package/dist/tools/getLibraryInsight.d.ts.map +1 -0
  33. package/dist/tools/getLibraryInsight.js +14 -0
  34. package/dist/tools/getLibraryInsight.js.map +1 -0
  35. package/dist/tools/getSimilarDocuments.d.ts +25 -0
  36. package/dist/tools/getSimilarDocuments.d.ts.map +1 -0
  37. package/dist/tools/getSimilarDocuments.js +28 -0
  38. package/dist/tools/getSimilarDocuments.js.map +1 -0
  39. package/dist/tools/produceFaq.d.ts +50 -0
  40. package/dist/tools/produceFaq.d.ts.map +1 -0
  41. package/dist/tools/produceFaq.js +52 -0
  42. package/dist/tools/produceFaq.js.map +1 -0
  43. package/dist/tools/scoringUtils.d.ts +23 -0
  44. package/dist/tools/scoringUtils.d.ts.map +1 -0
  45. package/dist/tools/scoringUtils.js +61 -0
  46. package/dist/tools/scoringUtils.js.map +1 -0
  47. package/dist/tools/searchByAuthor.d.ts +15 -0
  48. package/dist/tools/searchByAuthor.d.ts.map +1 -0
  49. package/dist/tools/searchByAuthor.js +27 -0
  50. package/dist/tools/searchByAuthor.js.map +1 -0
  51. package/dist/tools/searchByKeywords.d.ts +16 -0
  52. package/dist/tools/searchByKeywords.d.ts.map +1 -0
  53. package/dist/tools/searchByKeywords.js +27 -0
  54. package/dist/tools/searchByKeywords.js.map +1 -0
  55. package/dist/tools/searchByTheme.d.ts +27 -0
  56. package/dist/tools/searchByTheme.d.ts.map +1 -0
  57. package/dist/tools/searchByTheme.js +27 -0
  58. package/dist/tools/searchByTheme.js.map +1 -0
  59. package/dist/tools/searchByTitle.d.ts +15 -0
  60. package/dist/tools/searchByTitle.d.ts.map +1 -0
  61. package/dist/tools/searchByTitle.js +27 -0
  62. package/dist/tools/searchByTitle.js.map +1 -0
  63. package/dist/tools/searchDocuments.d.ts +14 -0
  64. package/dist/tools/searchDocuments.d.ts.map +1 -0
  65. package/dist/tools/searchDocuments.js +28 -0
  66. package/dist/tools/searchDocuments.js.map +1 -0
  67. package/package.json +55 -0
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Cirrusly Clever
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
package/README.md ADDED
@@ -0,0 +1,421 @@
1
+ # Assay MCP Server
2
+
3
+ Connect Claude Desktop to your [Assay](https://assay.cirrusly-clever.com) document library. Search, explore, and extract knowledge from your research documents directly from Claude conversations.
4
+
5
+ ## Overview
6
+
7
+ The Assay MCP Server provides Claude Desktop with access to your Assay document library through the Model Context Protocol (MCP). It enables Claude to:
8
+
9
+ - **Search** your library by themes, keywords, authors, and titles
10
+ - **Retrieve** document summaries (comprehensive, casual, and FAQs)
11
+ - **Discover** related documents using Jaccard similarity
12
+ - **Explore** themes and generate insights
13
+ - **Compare** documents and synthesize FAQs across multiple sources
14
+
15
+ All tools search both your **private** and **public** document collections, giving Claude access to your entire research library.
16
+
17
+ ## Features
18
+
19
+ - 🔍 **13 powerful tools** for document exploration and analysis
20
+ - 🎯 **Jaccard similarity scoring** for intelligent document matching
21
+ - 🔐 **Secure authentication** via Firebase ID tokens
22
+ - 📊 **Theme-based organization** with 180+ canonical themes
23
+ - 🚀 **Zero GenAI costs** - tools only retrieve data, Claude does the synthesis (or optional server-side synthesis with your API key)
24
+ - 🌐 **Public + Private** - searches across both collections
25
+
26
+ ## Installation
27
+
28
+ ### Prerequisites
29
+
30
+ - Node.js 18+
31
+ - An Assay account ([sign up here](https://assay.cirrusly-clever.com))
32
+ - Claude Desktop installed
33
+
34
+ ### Install from Source
35
+
36
+ ```bash
37
+ git clone https://github.com/cirruslycurious/assay-mcp-server.git
38
+ cd assay-mcp-server
39
+ npm install
40
+ npm run build
41
+ ```
42
+
43
+ ### Global Installation (After Publishing)
44
+
45
+ ```bash
46
+ npm install -g @assay/mcp-server
47
+ ```
48
+
49
+ ## Quick Start
50
+
51
+ **New to Assay MCP?** See the [Complete Setup Guide](./SETUP_GUIDE.md) for detailed instructions on:
52
+ - Getting your Firebase token
53
+ - Optional: Setting up server-side synthesis with Claude API key
54
+
55
+ ## Getting Your Firebase Token
56
+
57
+ 1. Visit [Assay Dashboard](https://assay.cirrusly-clever.com/dashboard)
58
+ 2. Sign in with Google (if not already signed in)
59
+ 3. Click the **"Get MCP Token"** button in the header
60
+ 4. Copy the token from the dialog
61
+
62
+ **Note:** Tokens expire after 1 hour. Generate a new token when needed.
63
+
64
+ ## Claude Desktop Configuration
65
+
66
+ Add the MCP server to your Claude Desktop configuration:
67
+
68
+ **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
69
+ **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
70
+ **Linux:** `~/.config/Claude/claude_desktop_config.json`
71
+
72
+ ### For Local Installation
73
+
74
+ ```json
75
+ {
76
+ "mcpServers": {
77
+ "assay": {
78
+ "command": "node",
79
+ "args": [
80
+ "/absolute/path/to/assay-mcp-server/dist/index.js",
81
+ "--token",
82
+ "YOUR_FIREBASE_TOKEN_HERE"
83
+ ]
84
+ }
85
+ }
86
+ }
87
+ ```
88
+
89
+ **Replace `/absolute/path/to/assay-mcp-server`** with your actual path, e.g.:
90
+ - macOS: `/Users/yourname/Documents/assay-mcp-server/dist/index.js`
91
+ - Linux: `/home/yourname/assay-mcp-server/dist/index.js`
92
+ - Windows: `C:\\Users\\yourname\\Documents\\assay-mcp-server\\dist\\index.js`
93
+
94
+ ### For Global Installation
95
+
96
+ ```json
97
+ {
98
+ "mcpServers": {
99
+ "assay": {
100
+ "command": "assay-mcp-server",
101
+ "args": ["--token", "YOUR_FIREBASE_TOKEN_HERE"]
102
+ }
103
+ }
104
+ }
105
+ ```
106
+
107
+ ### Using Environment Variable
108
+
109
+ ```json
110
+ {
111
+ "mcpServers": {
112
+ "assay": {
113
+ "command": "assay-mcp-server",
114
+ "env": {
115
+ "ASSAY_FIREBASE_TOKEN": "YOUR_FIREBASE_TOKEN_HERE",
116
+ "CLAUDE_API_KEY": "YOUR_CLAUDE_API_KEY_HERE"
117
+ }
118
+ }
119
+ }
120
+ }
121
+ ```
122
+
123
+ **Optional Environment Variables:**
124
+ - `FIREBASE_API_KEY` - Override Firebase Web API key (default: Assay service key)
125
+ - Only needed if you want to use your own Firebase project
126
+ - Get from: Firebase Console > Project Settings > General > Your apps
127
+ - `ASSAY_FUNCTIONS_BASE_URL` - Override Cloud Functions endpoint (default: `https://us-east4-pdfsummaries.cloudfunctions.net`)
128
+ - `CLAUDE_API_KEY` - For optional server-side synthesis
129
+
130
+ **⚠️ Optional: Server-Side Synthesis**
131
+
132
+ Server-side synthesis is **optional**. The MCP server works great without it!
133
+
134
+ **Without API key (Default):**
135
+ - Tools return raw data from your collection
136
+ - Claude Desktop synthesizes responses using the retrieved data
137
+ - Zero additional costs - you're already using Claude Desktop
138
+
139
+ **With API key (Optional):**
140
+ - Tools can return pre-synthesized responses using Claude API
141
+ - Requires your own Anthropic API key (set spending limits for safety)
142
+ - Add `CLAUDE_API_KEY` to your config (see [Setup Guide](./SETUP_GUIDE.md))
143
+ - Falls back to raw data if API key is missing or invalid
144
+
145
+ **See the [Complete Setup Guide](./SETUP_GUIDE.md) for detailed instructions on optional server-side synthesis.**
146
+
147
+ After updating the config file, **restart Claude Desktop** to load the MCP server.
148
+
149
+ ## Available Tools
150
+
151
+ ### Search Tools
152
+
153
+ #### 1. `search_documents`
154
+ Search your library by theme name, author, or document title. Searches both private and public collections.
155
+
156
+ **Example prompts:**
157
+ - "Search for documents about AI safety"
158
+ - "Find papers on zero trust architecture"
159
+ - "Show me documents by Anthropic researchers"
160
+
161
+ #### 2. `search_by_author`
162
+ Search specifically by author name.
163
+
164
+ **Example prompts:**
165
+ - "Find all documents by Brian Singer"
166
+ - "Show me papers from OpenAI researchers"
167
+
168
+ #### 3. `search_by_title`
169
+ Search by document title keywords.
170
+
171
+ **Example prompts:**
172
+ - "Find documents with 'red team' in the title"
173
+ - "Search for papers titled 'LLM safety'"
174
+
175
+ #### 4. `search_by_keywords`
176
+ Search in document keywords, key concepts, and key phrases.
177
+
178
+ **Example prompts:**
179
+ - "Find documents about 'machine learning' and 'neural networks'"
180
+ - "Search for 'zero trust' and 'confidential computing'"
181
+
182
+ ### Document Retrieval
183
+
184
+ #### 5. `get_document_summary`
185
+ Get comprehensive, casual, or FAQ summaries for a specific document.
186
+
187
+ **Parameters:**
188
+ - `documentId`: The document ID
189
+ - `summaryType`: `"comprehensive"`, `"casual"`, or `"faq"`
190
+
191
+ **Example prompts:**
192
+ - "Get the comprehensive summary of document abc123"
193
+ - "What's the casual summary for the governance paper?"
194
+ - "Show me FAQs for document xyz789"
195
+
196
+ #### 6. `get_similar_documents`
197
+ Find documents similar to a given document using Jaccard similarity based on theme overlap.
198
+
199
+ **Returns:** Similar documents with similarity scores (High ≥35%, Moderate ≥20%, Low <20%)
200
+
201
+ **Example prompts:**
202
+ - "What documents are similar to document abc123?"
203
+ - "Find related papers to the prompt injection document"
204
+
205
+ ### Exploration Tools
206
+
207
+ #### 7. `browse_themes`
208
+ Browse the canonical theme taxonomy. Without a domain, returns all L0 domains with document counts. With a domain, returns L1 themes within that domain.
209
+
210
+ **Example prompts:**
211
+ - "What themes do I have documents in?"
212
+ - "Show me all themes under Cybersecurity"
213
+ - "Browse themes in the Artificial Intelligence domain"
214
+
215
+ #### 8. `get_library_insight`
216
+ Get your AI-generated personalized insight about your research profile.
217
+
218
+ **Example prompts:**
219
+ - "What does my document collection say about my research interests?"
220
+ - "Get my library insight"
221
+
222
+ ### Advanced Analysis
223
+
224
+ #### 9. `ask_question`
225
+ Ask a question about your library. The tool searches for relevant documents and returns their summaries for Claude to synthesize an answer.
226
+
227
+ **With Claude API key:** Returns a synthesized answer (server-side).
228
+ **Without API key:** Returns raw document summaries for Claude Desktop to synthesize.
229
+
230
+ **Example prompts:**
231
+ - "If I wanted to automate Red Team exercises, what should I consider?"
232
+ - "What are the key considerations for implementing zero trust?"
233
+ - "What do my documents say about AI safety frameworks?"
234
+
235
+ #### 10. `compare_documents`
236
+ Compare up to 25 documents selected by themes, keywords, or authors. Returns documents sorted by relevance score.
237
+
238
+ **With Claude API key:** Returns a synthesized comparison (server-side).
239
+ **Without API key:** Returns raw document summaries for Claude Desktop to synthesize.
240
+
241
+ **Parameters:**
242
+ - `themes`: Array of theme IDs (e.g., `["CYBERSECURITY", "ARTIFICIAL_INTELLIGENCE.AI_ARCHITECTURES"]`)
243
+ - `keywords`: Array of keywords
244
+ - `authors`: Array of author names
245
+
246
+ **Example prompts:**
247
+ - "Compare documents about AI safety and cybersecurity"
248
+ - "Compare papers by Anthropic and OpenAI on AI alignment"
249
+
250
+ #### 11. `produce_faq`
251
+ Generate FAQs from up to 25 documents selected by themes, keywords, or authors.
252
+
253
+ **With Claude API key:** Returns a synthesized FAQ (server-side).
254
+ **Without API key:** Returns raw document FAQs for Claude Desktop to synthesize.
255
+
256
+ **Parameters:** Same as `compare_documents`
257
+
258
+ **Example prompts:**
259
+ - "Generate FAQs about AI architectures and cybersecurity"
260
+ - "Create FAQs from documents about zero trust by these authors"
261
+
262
+ ## How It Compares
263
+
264
+ The Assay MCP Server offers unique advantages over traditional RAG systems and file-based AI assistants:
265
+
266
+ | Feature | Assay MCP | Traditional RAG | ChatGPT with Files |
267
+ |---------|-----------|-----------------|-------------------|
268
+ | **Pre-processed summaries** | ✅ 3 formats (comprehensive, casual, FAQs) | ❌ Processes on-the-fly | ❌ Processes on-the-fly |
269
+ | **Theme-based organization** | ✅ 180 canonical themes | ❌ No structured taxonomy | ❌ No structured taxonomy |
270
+ | **Similarity algorithm** | ✅ Jaccard (theme overlap) | Vector embeddings | Vector embeddings |
271
+ | **Multi-format summaries** | ✅ Comprehensive, Casual, FAQs | Single format | Single format |
272
+ | **Cost per query** | ✅ $0 (Firestore only) | $0.01-0.10 (embeddings + LLM) | Included in subscription |
273
+ | **Conversational interface** | ✅ Via Claude Desktop | ✅ Via chat interface | ✅ Native |
274
+ | **Public + Private collections** | ✅ Both searchable | ❌ Single collection | ❌ Single collection |
275
+ | **Cross-document analysis** | ✅ Compare, synthesize FAQs | Limited | Limited |
276
+ | **Structured metadata** | ✅ Authors, dates, keywords | ❌ Unstructured | ❌ Unstructured |
277
+ | **No document storage** | ✅ Summaries only | ❌ Stores full documents | ❌ Stores full documents |
278
+
279
+ ### Key Advantages
280
+
281
+ **1. Zero-cost queries**
282
+ - Traditional RAG requires embedding generation and LLM calls for every query
283
+ - Assay MCP only queries Firestore (no AI costs)
284
+ - Claude does the synthesis (you're already paying for Claude)
285
+
286
+ **2. Pre-processed intelligence**
287
+ - Documents are analyzed once during upload
288
+ - Multiple summary formats available instantly
289
+ - No waiting for processing during queries
290
+
291
+ **3. Structured discovery**
292
+ - 180 canonical themes enable precise filtering
293
+ - Jaccard similarity finds documents with shared research areas
294
+ - Not just keyword matching - semantic theme understanding
295
+
296
+ **4. Multi-collection access**
297
+ - Search both your private documents and public collection
298
+ - Discover research from other users
299
+ - Privacy-respecting (only shows what you have access to)
300
+
301
+ ## How It Works
302
+
303
+ ### Relevance Scoring
304
+
305
+ All tools use **Jaccard similarity** for relevance scoring:
306
+
307
+ - **Themes**: Weighted Jaccard (L1 themes = 0.8, L0 domains = 0.2)
308
+ - **Keywords**: Standard Jaccard similarity
309
+ - **Authors**: Standard Jaccard similarity
310
+ - **Combined**: Weighted average (themes = 0.6, keywords = 0.25, authors = 0.15)
311
+
312
+ **Similarity Levels:**
313
+ - **High**: ≥35% similarity
314
+ - **Moderate**: ≥20% similarity
315
+ - **Low**: <20% similarity
316
+
317
+ ### Data Flow
318
+
319
+ 1. **Tool Call**: Claude calls an MCP tool with parameters
320
+ 2. **Authentication**: Server verifies Firebase ID token
321
+ 3. **Query**: Searches Firestore for matching documents
322
+ 4. **Scoring**: Calculates Jaccard similarity scores
323
+ 5. **Retrieval**: Fetches document summaries and metadata
324
+ 6. **Return**: Structured JSON with documents and summaries
325
+ 7. **Synthesis**: Claude uses the data to answer questions or generate insights
326
+
327
+ ### Privacy & Security
328
+
329
+ - **Token-based authentication**: Each request requires a valid Firebase ID token
330
+ - **User-scoped queries**: Only returns documents the user has access to
331
+ - **Private + Public**: Searches both collections but respects visibility settings
332
+ - **No document storage**: Tools only retrieve summaries, not full document content
333
+
334
+ ## Development
335
+
336
+ ### Setup
337
+
338
+ ```bash
339
+ # Install dependencies
340
+ npm install
341
+
342
+ # Build TypeScript
343
+ npm run build
344
+
345
+ # Run in development mode
346
+ npm run dev -- --token <your-token>
347
+ ```
348
+
349
+ ### Project Structure
350
+
351
+ ```
352
+ assay-mcp-server/
353
+ ├── src/
354
+ │ ├── index.ts # Main MCP server entry point
355
+ │ ├── firebase.ts # Firebase REST API integration (no Admin SDK needed!)
356
+ │ └── tools/ # Individual tool implementations
357
+ │ ├── searchDocuments.ts
358
+ │ ├── getDocumentSummary.ts
359
+ │ ├── getSimilarDocuments.ts
360
+ │ ├── searchByAuthor.ts
361
+ │ ├── searchByTitle.ts
362
+ │ ├── searchByKeywords.ts
363
+ │ ├── getLibraryInsight.ts
364
+ │ ├── browseThemes.ts
365
+ │ ├── askQuestion.ts
366
+ │ ├── compareDocuments.ts
367
+ │ ├── produceFaq.ts
368
+ │ └── scoringUtils.ts # Shared scoring functions
369
+ ├── dist/ # Compiled JavaScript
370
+ └── package.json
371
+ ```
372
+
373
+ ### Adding New Tools
374
+
375
+ 1. Create a new file in `src/tools/`
376
+ 2. Export a `Tool` definition and implementation function
377
+ 3. Import and register in `src/index.ts`
378
+ 4. Rebuild: `npm run build`
379
+
380
+ ## Troubleshooting
381
+
382
+ ### Server Disconnects
383
+
384
+ - **Token expired**: Generate a new token from the Assay dashboard (tokens expire after 1 hour)
385
+ - **Invalid token**: Make sure you copied the full token without extra characters
386
+ - **Path issues**: Verify the absolute path in Claude Desktop config is correct
387
+
388
+ ### No Results Returned
389
+
390
+ - **Check authentication**: Ensure you're signed in to Assay
391
+ - **Verify documents**: Make sure you have documents uploaded and processed
392
+ - **Check visibility**: Public documents are searchable, private documents only by owner
393
+
394
+ ### Build Errors
395
+
396
+ - **Node version**: Ensure Node.js 18+ is installed
397
+ - **Dependencies**: Run `npm install` to ensure all packages are installed
398
+ - **TypeScript**: Check `tsconfig.json` is properly configured
399
+
400
+ ## Contributing
401
+
402
+ Contributions welcome! Please open an issue or submit a pull request.
403
+
404
+ ## License
405
+
406
+ MIT License - see LICENSE file for details
407
+
408
+ ## Links
409
+
410
+ - **Assay Web App**: https://assay.cirrusly-clever.com
411
+ - **MCP Documentation**: https://modelcontextprotocol.io
412
+
413
+ ## Support
414
+
415
+ For issues, questions, or feature requests:
416
+ - Open an issue on GitHub
417
+ - Contact: support@cirrusly-clever.com
418
+
419
+ ---
420
+
421
+ **Made with ❤️ by [Cirrusly Clever](https://cirrusly-clever.com)**
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Firebase integration using Cloud Function proxies
3
+ * MCP server is now a thin client that calls Assay Cloud Functions
4
+ * No Firestore access needed - all handled by backend!
5
+ */
6
+ /**
7
+ * Verify Firebase ID token using Firebase Auth REST API
8
+ */
9
+ export declare function verifyToken(token: string): Promise<{
10
+ uid: string;
11
+ email?: string;
12
+ }>;
13
+ /**
14
+ * Get Claude API key from environment
15
+ */
16
+ export declare function getClaudeApiKey(): string | undefined;
17
+ /**
18
+ * Call a Cloud Function with user's ID token
19
+ */
20
+ export declare function callCloudFunction(functionName: string, data: any, token: string): Promise<any>;
21
+ /**
22
+ * Firestore wrapper that calls Cloud Functions instead
23
+ * This maintains the same API so existing code doesn't break
24
+ */
25
+ export declare function getFirestore(token: string): {
26
+ collection: (collectionName: string) => {
27
+ where: (field: string, operator: string, value: any) => {
28
+ where: (field2: string, operator2: string, value2: any) => {
29
+ get: () => Promise<{
30
+ docs: never[];
31
+ }>;
32
+ };
33
+ get: () => Promise<{
34
+ docs: never[];
35
+ }>;
36
+ };
37
+ doc: (docId: string) => {
38
+ get: () => Promise<{
39
+ exists: boolean;
40
+ id: string;
41
+ data: () => {};
42
+ }>;
43
+ };
44
+ get: () => Promise<{
45
+ docs: never[];
46
+ }>;
47
+ };
48
+ };
49
+ /**
50
+ * Initialize Firebase (no-op for this approach)
51
+ */
52
+ export declare function initializeFirebase(): void;
53
+ //# sourceMappingURL=firebase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firebase.d.ts","sourceRoot":"","sources":["../src/firebase.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAYH;;GAEG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA+BzF;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,SAAS,CAEpD;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,GAAG,EACT,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,GAAG,CAAC,CAwCd;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM;iCAET,MAAM;uBAClB,MAAM,YAAY,MAAM,SAAS,GAAG;4BACjC,MAAM,aAAa,MAAM,UAAU,GAAG;;;;;;;;;qBAW3C,MAAM;;;;;;;;;;;EAUxB;AAID;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Firebase integration using Cloud Function proxies
3
+ * MCP server is now a thin client that calls Assay Cloud Functions
4
+ * No Firestore access needed - all handled by backend!
5
+ */
6
+ const ASSAY_FUNCTIONS_BASE_URL = process.env.ASSAY_FUNCTIONS_BASE_URL ||
7
+ 'https://us-east4-pdfsummaries.cloudfunctions.net';
8
+ // Firebase Web API key for token verification
9
+ // This is a PUBLIC API key (Firebase Web API keys are designed to be public)
10
+ // Security is provided by API restrictions in Google Cloud Console, not by keeping it secret
11
+ // Users can override with FIREBASE_API_KEY env var if they want to use their own Firebase project
12
+ const FIREBASE_API_KEY = process.env.FIREBASE_API_KEY ||
13
+ 'AIzaSyBBq7eyl1vvcZWTdM1CmnPjlcX0OEsr5Ws';
14
+ /**
15
+ * Verify Firebase ID token using Firebase Auth REST API
16
+ */
17
+ export async function verifyToken(token) {
18
+ try {
19
+ const response = await fetch(`https://identitytoolkit.googleapis.com/v1/accounts:lookup?key=${FIREBASE_API_KEY}`, {
20
+ method: 'POST',
21
+ headers: {
22
+ 'Content-Type': 'application/json',
23
+ },
24
+ body: JSON.stringify({ idToken: token }),
25
+ });
26
+ if (!response.ok) {
27
+ const errorData = (await response.json().catch(() => ({})));
28
+ throw new Error(`Token verification failed: ${errorData.error?.message || response.statusText}`);
29
+ }
30
+ const data = (await response.json());
31
+ if (!data.users || data.users.length === 0) {
32
+ throw new Error('Invalid token: no user found');
33
+ }
34
+ const user = data.users[0];
35
+ return {
36
+ uid: user.localId,
37
+ email: user.email,
38
+ };
39
+ }
40
+ catch (error) {
41
+ throw new Error(`Token verification failed: ${error instanceof Error ? error.message : String(error)}`);
42
+ }
43
+ }
44
+ /**
45
+ * Get Claude API key from environment
46
+ */
47
+ export function getClaudeApiKey() {
48
+ return process.env.CLAUDE_API_KEY || process.env.ANTHROPIC_API_KEY;
49
+ }
50
+ /**
51
+ * Call a Cloud Function with user's ID token
52
+ */
53
+ export async function callCloudFunction(functionName, data, token) {
54
+ // Include Claude API key if available
55
+ const claudeApiKey = getClaudeApiKey();
56
+ if (claudeApiKey) {
57
+ data.claudeApiKey = claudeApiKey;
58
+ }
59
+ const url = `${ASSAY_FUNCTIONS_BASE_URL}/${functionName}`;
60
+ const response = await fetch(url, {
61
+ method: 'POST',
62
+ headers: {
63
+ 'Authorization': `Bearer ${token}`,
64
+ 'Content-Type': 'application/json',
65
+ },
66
+ body: JSON.stringify({ data }),
67
+ });
68
+ if (!response.ok) {
69
+ const errorText = await response.text();
70
+ let errorData;
71
+ try {
72
+ errorData = JSON.parse(errorText);
73
+ }
74
+ catch {
75
+ errorData = { error: { message: errorText } };
76
+ }
77
+ throw new Error(`Cloud Function ${functionName} failed: ${errorData.error?.message || response.statusText} (${response.status})`);
78
+ }
79
+ const result = (await response.json());
80
+ // Firebase Callable Functions return { result: ... } or { error: ... }
81
+ if (result.error) {
82
+ throw new Error(`Cloud Function error: ${result.error.message || JSON.stringify(result.error)}`);
83
+ }
84
+ return result.result;
85
+ }
86
+ /**
87
+ * Firestore wrapper that calls Cloud Functions instead
88
+ * This maintains the same API so existing code doesn't break
89
+ */
90
+ export function getFirestore(token) {
91
+ return {
92
+ collection: (collectionName) => ({
93
+ where: (field, operator, value) => ({
94
+ where: (field2, operator2, value2) => ({
95
+ get: async () => {
96
+ // This is a simplified wrapper - actual queries go through Cloud Functions
97
+ // For now, return empty - individual tools will call Cloud Functions directly
98
+ return { docs: [] };
99
+ },
100
+ }),
101
+ get: async () => {
102
+ return { docs: [] };
103
+ },
104
+ }),
105
+ doc: (docId) => ({
106
+ get: async () => {
107
+ return { exists: false, id: docId, data: () => ({}) };
108
+ },
109
+ }),
110
+ get: async () => {
111
+ return { docs: [] };
112
+ },
113
+ }),
114
+ };
115
+ }
116
+ // callCloudFunction is already exported above
117
+ /**
118
+ * Initialize Firebase (no-op for this approach)
119
+ */
120
+ export function initializeFirebase() {
121
+ // No initialization needed - we use Cloud Functions
122
+ }
123
+ //# sourceMappingURL=firebase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firebase.js","sourceRoot":"","sources":["../src/firebase.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}