Conversation
Add Smithery install instructions and update package.json
Added badge to README.md
This PR adds a badge for the Exa MCP Server server listing in Glama MCP server directory. <a href="https://glama.ai/mcp/servers/8gfe5kbp5y"><img width="380" height="200" src="https://glama.ai/mcp/servers/8gfe5kbp5y/badge" alt="Exa Server MCP server" /></a> Glama performs regular codebase and documentation scans to: * Confirm that the MCP server is working as expected * Confirm that there are no obvious security issues with dependencies of the server * Extract server characteristics such as tools, resources, prompts, and required parameters. This badge helps your users to quickly asses that the MCP server is safe, server capabilities, and instructions for installing the server.
Deployment: Dockerfile and Smithery config
Fix npm install running prepare in Docker
…th more exa api features
Create LICENSE
add MCP server badge
…ure with selectable tools
- Add Dockerfile with Node.js Alpine base image - Configure multi-stage build to minimize image size - Add .dockerignore to exclude unnecessary files - Enable running MCP server in containerized environment 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Changed default transport from HTTP to STDIO (MCP standard) - Added backward-compatible error handling utilities - Implemented basic protocol handlers (ping, logging stubs, sampling stubs) - Created feature flag system for gradual adoption - Prepared resource module structure for future implementation - All changes maintain backward compatibility Features can be enabled via environment variables: - MCP_FEATURES_LOGGING=true - MCP_FEATURES_SAMPLING=true - MCP_FEATURES_RESOURCES=true (prepared but not implemented) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Add automatic pagination to prevent token overflow - Implement polling for async operations (search, enhance) - Use fixed intervals instead of exponential backoff per user request - Add waitForResults option to search and enhancement operations - Update README with pagination and polling best practices - Fix getSearchResults method name error - Search polling: 2s intervals for up to 1 minute - Enhancement polling: 3s intervals for up to 2 minutes 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Update Dockerfile to start in HTTP mode for containerized deployments - Add PORT environment variable support for Smithery compatibility - Maintain backward compatibility with local STDIO development - Add debugging documentation for connection analysis Fixes MCP error -32001 timeout during Smithery tool discovery by ensuring Docker container starts in HTTP mode while preserving STDIO default for local Claude Code usage. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Remove duplicate implementation reports and analysis files - Clean up temporary parallel implementation artifacts - Keep essential docs: README, CLAUDE.md, connection analysis, Smithery logs - Remove obsolete test configs and OpenAPI specs Streamlines repository structure while preserving critical documentation for development and deployment workflows. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
- Change ping handler to return empty object {} instead of custom fields
- Removes 'pong' and 'timestamp' fields that caused schema validation errors
- Follows MCP specification for ping response format
Fixes Smithery tool scanning error: "Unrecognized key(s) in object: 'pong', 'timestamp'"
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <[email protected]>
refactor: Add Smithery-compatible default export and configSchema
- Remove CONNECTION_ISSUES_ANALYSIS.md, SMITHERY_LOGS.md, and debug-wrapper.js - Update .gitignore and .npmignore configurations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
…knowledge-graph
…ge-graph-for-webset
- Changed console.log to console.error in stdio mode to prevent corrupting JSON-RPC protocol - MCP protocol uses stdout for communication, so logging must go to stderr - Fixes 'invalid character' errors when orchestrator connects to subprocess
…ompts Add three new orchestration prompts for common Websets use cases: - Marketing: competitor monitoring, brand health tracking, share of voice analysis - CRM: lead discovery, ICP matching, intent scoring, contact enrichment - Hiring: dual-mode support for recruiters (passive candidate sourcing) and job seekers (target company tracking) Each orchestration includes: - Parameterized markdown workflows with real tool calls - Step-by-step instructions for web_search_exa, websets_manager, knowledge_graph - Multiple real-world examples and best practices - Comprehensive troubleshooting and FAQs - Fixed: attribute empty results to technical errors, not query issues These prompts are designed to be tested via MCPJam and can also be served as resources via parameterized URIs for maximum client compatibility. Co-authored-by: Claude <[email protected]>
…, and hiring with URI parameterization
Registers marketing, CRM, and hiring orchestration resources with MCP server for client access via resource URIs. Integrates resolveOrchestrationResource and resource callback handlers in server bootstrap. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
…dler Simplify resource registration by consolidating three separate resource handlers into a single catch-all handler for websets://orchestrations/*. This improves maintainability while supporting all orchestration types (marketing, CRM, hiring) through a unified resolution mechanism. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Documentation for three MCP orchestration prompts: - Marketing: Competitor monitoring and brand health tracking - CRM: Lead discovery and account-based marketing - Hiring: Recruiter candidate sourcing and job seeker company tracking Includes parameter details, example calls, integration guidance, and best practices. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| private async processWithTimeout(event: WebsetEvent, handlers: EventHandler[]): Promise<void> { | ||
| const timeoutPromise = new Promise<never>((_, reject) => { | ||
| setTimeout(() => { | ||
| reject(new Error(`Event processing timeout after ${this.config.timeout}ms`)); | ||
| }, this.config.timeout); | ||
| }); | ||
|
|
||
| const processingPromise = this.executeHandlers(event, handlers); | ||
|
|
||
| await Promise.race([processingPromise, timeoutPromise]); |
There was a problem hiding this comment.
Cancel timeout promise in processWithTimeout
The timeout in processWithTimeout rejects after this.config.timeout even when handler execution already finished successfully, because the setTimeout is never cleared. After Promise.race resolves, the pending promise still rejects and nothing awaits it, which will emit an unhandled rejection for every processed event and can crash Node in strict modes. Store the timer handle and clear it once processingPromise settles before returning.
Useful? React with 👍 / 👎.
| start(): void { | ||
| if (this.isPolling || this.isShuttingDown) { | ||
| return; | ||
| } | ||
|
|
||
| this.isPolling = true; | ||
| this.stats.status = 'polling'; | ||
| this.emit('started'); | ||
|
|
||
| // Start immediate poll, then set up interval | ||
| this.poll().catch(error => { | ||
| console.error('Initial poll failed:', error); | ||
| }); | ||
|
|
||
| this.pollingInterval = setInterval(() => { | ||
| if (!this.isShuttingDown) { | ||
| this.poll().catch(error => { | ||
| console.error('Polling error:', error); | ||
| }); |
There was a problem hiding this comment.
Prevent concurrent polls in EventPoller
Calling start() schedules poll() on a fixed interval without checking whether a previous poll is still running. When long‑polling or slow requests exceed config.interval, the next interval fires and a second poll() starts with the same cursor, producing concurrent requests that can double‑process or miss events and inflate failure counts. Guard poll() with an in‑flight flag or await the previous invocation before scheduling another tick.
Useful? React with 👍 / 👎.
| private async processEvent(queuedEvent: QueuedEvent): Promise<void> { | ||
| const startTime = Date.now(); | ||
| const eventId = queuedEvent.event.id; | ||
|
|
||
| this.processing.add(eventId); | ||
| this.stats.processing = this.processing.size; | ||
| queuedEvent.attempts++; | ||
|
|
||
| try { | ||
| this.emit('processing', queuedEvent); | ||
|
|
||
| // Emit the event for handlers to process | ||
| this.emit('event', queuedEvent.event); | ||
|
|
||
| // Remove from queue on successful processing |
There was a problem hiding this comment.
Retry logic never sees async handler failures
EventQueue.processEvent treats an event as successfully processed immediately after this.emit('event', queuedEvent.event) and removes it from the queue. Because EventEmitter executes listeners synchronously, any asynchronous handler that rejects later will not throw inside this try/catch, so the queue never schedules a retry and lost work goes unnoticed. Wrap listener invocation in await Promise.all(...) or require handlers to be synchronous so async failures propagate before removing the item.
Useful? React with 👍 / 👎.
No description provided.