Skip to content

Commit 2791859

Browse files
authored
Merge pull request #12 from vrknetha/feature/remove-rate-limit
Feature/remove rate limit
2 parents 5ad8b85 + 540b1ef commit 2791859

File tree

2 files changed

+18
-95
lines changed

2 files changed

+18
-95
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mcp-server-firecrawl",
3-
"version": "1.2.2",
3+
"version": "1.2.3",
44
"description": "MCP server for FireCrawl web scraping integration. Supports both cloud and self-hosted instances. Features include web scraping, batch processing, structured data extraction, and LLM-powered content analysis.",
55
"type": "module",
66
"bin": "dist/src/index.js",

src/index.ts

Lines changed: 17 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -674,58 +674,14 @@ const client = new FirecrawlApp({
674674
...(FIRE_CRAWL_API_URL ? { apiUrl: FIRE_CRAWL_API_URL } : {}),
675675
});
676676

677-
// Simplify rate limiting to work with SDK's rate limiting
678-
const RATE_LIMIT = {
679-
perMinute: 3,
680-
waitTime: 25000, // 25 seconds in milliseconds
681-
};
682-
683-
const requestCount = {
684-
minute: 0,
685-
lastReset: Date.now(),
686-
};
687-
688-
async function checkRateLimit(): Promise<void> {
689-
const now = Date.now();
690-
691-
// Reset counter if minute has passed
692-
if (now - requestCount.lastReset > 60000) {
693-
requestCount.minute = 0;
694-
requestCount.lastReset = now;
695-
server.sendLoggingMessage({
696-
level: 'info',
697-
data: 'Rate limit counter reset',
698-
});
699-
}
700-
701-
// Check if we've hit the per-minute limit
702-
if (requestCount.minute >= RATE_LIMIT.perMinute) {
703-
server.sendLoggingMessage({
704-
level: 'warning',
705-
data: `Rate limit reached: ${RATE_LIMIT.perMinute} requests per minute`,
706-
});
707-
throw new Error(
708-
`Rate limit reached: ${RATE_LIMIT.perMinute} requests per minute`
709-
);
710-
}
711-
712-
requestCount.minute++;
713-
}
714-
715-
// Add after imports
716-
717-
// Add configuration for retries and delays
677+
// Configuration for retries and monitoring
718678
const CONFIG = {
719679
retry: {
720680
maxAttempts: 3,
721681
initialDelay: 1000,
722682
maxDelay: 10000,
723683
backoffFactor: 2,
724684
},
725-
batch: {
726-
delayBetweenRequests: 2000,
727-
maxParallelOperations: 3,
728-
},
729685
credit: {
730686
warningThreshold: 1000,
731687
criticalThreshold: 100,
@@ -831,52 +787,25 @@ async function processBatchOperation(
831787
operation.status = 'processing';
832788
let totalCreditsUsed = 0;
833789

834-
// Process in chunks to respect rate limits
835-
const chunkSize = RATE_LIMIT.perMinute;
836-
const chunks = [];
837-
for (let i = 0; i < operation.urls.length; i += chunkSize) {
838-
chunks.push(operation.urls.slice(i, i + chunkSize));
839-
}
840-
841-
// Create parallel processor with limited concurrency
842-
const parallelQueue = new PQueue({
843-
concurrency: CONFIG.batch.maxParallelOperations,
844-
interval: 1000,
845-
intervalCap: RATE_LIMIT.perMinute,
846-
});
847-
848-
const results = await Promise.all(
849-
chunks.map((chunk) =>
850-
parallelQueue.add(async () => {
851-
await checkRateLimit();
852-
853-
const response = await withRetry(
854-
async () => client.asyncBatchScrapeUrls(chunk, operation.options),
855-
`batch ${operation.id} chunk processing`
856-
);
857-
858-
// Track credits if using cloud API and credits are available
859-
if (!FIRE_CRAWL_API_URL && hasCredits(response)) {
860-
totalCreditsUsed += response.creditsUsed;
861-
await updateCreditUsage(response.creditsUsed);
862-
}
863-
864-
operation.progress.completed += chunk.length;
865-
server.sendLoggingMessage({
866-
level: 'info',
867-
data: `Batch ${operation.id}: Processed ${operation.progress.completed}/${operation.progress.total} URLs`,
868-
});
790+
// Use library's built-in batch processing
791+
const response = await withRetry(
792+
async () =>
793+
client.asyncBatchScrapeUrls(operation.urls, operation.options),
794+
`batch ${operation.id} processing`
795+
);
869796

870-
// Add delay between chunks
871-
await delay(CONFIG.batch.delayBetweenRequests);
797+
if (!response.success) {
798+
throw new Error(response.error || 'Batch operation failed');
799+
}
872800

873-
return response;
874-
})
875-
)
876-
);
801+
// Track credits if using cloud API
802+
if (!FIRE_CRAWL_API_URL && hasCredits(response)) {
803+
totalCreditsUsed += response.creditsUsed;
804+
await updateCreditUsage(response.creditsUsed);
805+
}
877806

878807
operation.status = 'completed';
879-
operation.result = results;
808+
operation.result = response;
880809

881810
// Log final credit usage for the batch
882811
if (!FIRE_CRAWL_API_URL) {
@@ -932,7 +861,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
932861
}
933862
const { url, ...options } = args;
934863
try {
935-
await checkRateLimit();
936864
const scrapeStartTime = Date.now();
937865
server.sendLoggingMessage({
938866
level: 'info',
@@ -1136,8 +1064,6 @@ ${
11361064
throw new Error('Invalid arguments for fire_crawl_search');
11371065
}
11381066
try {
1139-
await checkRateLimit();
1140-
11411067
const response = await withRetry(
11421068
async () => client.search(args.query, args),
11431069
'search operation'
@@ -1187,7 +1113,6 @@ ${result.markdown ? `\nContent:\n${result.markdown}` : ''}`
11871113
}
11881114

11891115
try {
1190-
await checkRateLimit();
11911116
const extractStartTime = Date.now();
11921117

11931118
server.sendLoggingMessage({
@@ -1353,9 +1278,7 @@ async function runServer() {
13531278

13541279
server.sendLoggingMessage({
13551280
level: 'info',
1356-
data: `Configuration: API URL: ${
1357-
FIRE_CRAWL_API_URL || 'default'
1358-
}, Rate Limit: ${RATE_LIMIT.perMinute}/minute`,
1281+
data: `Configuration: API URL: ${FIRE_CRAWL_API_URL || 'default'}`,
13591282
});
13601283

13611284
console.error('FireCrawl MCP Server running on stdio');

0 commit comments

Comments
 (0)