BioMCP
by acashmoney
- src
- server
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
analyzeActiveSite,
analyzeActiveSiteSchema
} from "../tools/analyzeActiveSite.js";
import {
searchDiseaseProteins,
searchDiseaseProteinsSchema
} from "../tools/searchDiseaseProteins.js";
// Keep-alive interval (ms) - Keep this under 30 seconds to prevent timeouts
const KEEP_ALIVE_INTERVAL = 25000;
/**
* Create and configure the MCP server
*/
export function createServer() {
const server = new McpServer({
name: "bio-mcp",
version: "0.1.0",
});
// Register the analyze-active-site tool
server.tool(
"analyze-active-site",
"Analyze the active site of a protein structure",
analyzeActiveSiteSchema,
analyzeActiveSite
);
// Register the search-disease-proteins tool
server.tool(
"search-disease-proteins",
"Search for proteins related to a disease",
searchDiseaseProteinsSchema,
searchDiseaseProteins
);
return server;
}
// Keep track of connection state and timers
let keepAliveInterval: NodeJS.Timeout | null = null;
let transport: StdioServerTransport | null = null;
/**
* Send a keep-alive message by executing a no-op ping that forces the transport to stay active
*/
function sendKeepAlive() {
console.error("Sending keep-alive ping");
console.error(`Keep-alive ping at ${new Date().toISOString()}`);
}
/**
* Clean up resources when shutting down
*/
function cleanup() {
console.error("Cleaning up resources...");
if (keepAliveInterval) {
clearInterval(keepAliveInterval);
keepAliveInterval = null;
}
if (transport) {
try {
server.close().catch(error => {
console.error("Error during close in cleanup:", error);
});
} catch (error) {
console.error("Error during cleanup:", error);
}
}
}
/**
* Set up signal handlers for graceful shutdown
*/
process.on('SIGINT', () => {
console.error("Received SIGINT signal");
cleanup();
process.exit(0);
});
process.on('SIGTERM', () => {
console.error("Received SIGTERM signal");
cleanup();
process.exit(0);
});
// Create the server instance
const server = createServer();
/**
* Main function to start the server
*/
export async function main() {
try {
transport = new StdioServerTransport();
await server.connect(transport);
console.error("PDB Analysis MCP Server running on stdio");
// Set up keep-alive interval
keepAliveInterval = setInterval(sendKeepAlive, KEEP_ALIVE_INTERVAL);
} catch (error) {
console.error("Fatal error in main():", error);
process.exit(1);
}
}
// Check if this file is being run directly
if (import.meta.url.endsWith(process.argv[1].replace(/^file:\/\//, ''))) {
// This is being run directly
main().catch((error) => {
console.error("Fatal error:", error);
process.exit(1);
});
}
// Export for testing
export { server };