Jake Shore d25ea2031b Gold standard upgrade: greenhouse, lever, loom
- Greenhouse: 29 tools (was 18), added interviews, scorecards, organization
- Lever: 26 tools (was 13), added tags, sources, expanded opportunities/postings
- Loom: 25 tools (was 14), added analytics, privacy, search, workspace members

All servers now have:
- main.ts with env validation & graceful shutdown
- server.ts with lazy-loaded tool modules
- Zod validation on all inputs
- Rich tool descriptions (when/why to use)
- Pagination support on all list_* tools
- Updated package.json (bin field, updated deps)
- Updated README with coverage manifests
- Old index.ts renamed to index.ts.bak
- Zero TypeScript errors (npx tsc --noEmit verified)
2026-02-14 05:52:42 -05:00

83 lines
2.3 KiB
JavaScript

#!/usr/bin/env node
/**
* Webflow MCP Server - Entry Point
* Provides tools for managing Webflow sites, CMS collections, pages, forms, assets, and webhooks
*/
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { WebflowMCPServer } from './server.js';
import { WebflowClient } from './client/webflow-client.js';
// Environment validation
const WEBFLOW_API_TOKEN = process.env.WEBFLOW_API_TOKEN;
if (!WEBFLOW_API_TOKEN) {
console.error('ERROR: WEBFLOW_API_TOKEN environment variable is required');
console.error('');
console.error('Get your API token from:');
console.error('1. Log in to https://webflow.com');
console.error('2. Go to Workspace Settings > Apps & Integrations');
console.error('3. Generate a new API token with required scopes');
console.error('');
console.error('Then set it in your environment:');
console.error(' export WEBFLOW_API_TOKEN="your_token_here"');
console.error('');
process.exit(1);
}
// Create API client
const client = new WebflowClient(WEBFLOW_API_TOKEN);
// Create MCP server
const server = new WebflowMCPServer(client);
// Create transport
const transport = new StdioServerTransport();
// Graceful shutdown handlers
let isShuttingDown = false;
const shutdown = async (signal: string) => {
if (isShuttingDown) return;
isShuttingDown = true;
console.error(`\nReceived ${signal}, shutting down gracefully...`);
try {
await transport.close();
console.error('Transport closed successfully');
} catch (error) {
console.error('Error during shutdown:', error);
}
process.exit(0);
};
process.on('SIGINT', () => shutdown('SIGINT'));
process.on('SIGTERM', () => shutdown('SIGTERM'));
// Global error handlers
process.on('uncaughtException', (error) => {
console.error('Uncaught exception:', error);
shutdown('uncaughtException');
});
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled rejection at:', promise, 'reason:', reason);
});
// Start server
async function main() {
try {
await server.connect(transport);
console.error('Webflow MCP server running on stdio');
console.error(`Environment: ${process.env.NODE_ENV || 'production'}`);
} catch (error) {
console.error('Failed to start server:', error);
process.exit(1);
}
}
main();