Skip to main content
Glama
index.js9.39 kB
#!/usr/bin/env node import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; import axios from "axios"; import * as dotenv from "dotenv"; // Load environment variables from .env file dotenv.config(); // Use environment variables with fallback values const ONYX_API_BASE = process.env.ONYX_API_BASE || ""; const LOG_LEVEL = process.env.LOG_LEVEL || "info"; // Configure logging based on LOG_LEVEL const logger = { info: (...args) => { if (["info", "debug"].includes(LOG_LEVEL)) { console.error("[INFO]", ...args); } }, debug: (...args) => { if (LOG_LEVEL === "debug") { console.error("[DEBUG]", ...args); } }, error: (...args) => { console.error("[ERROR]", ...args); }, warn: (...args) => { if (["info", "debug", "warn"].includes(LOG_LEVEL)) { console.error("[WARN]", ...args); } }, }; async function makeOnyxRequest(url, body) { const headers = { "Content-Type": "application/json", }; try { const response = await axios.post(url, body, { headers }); if (!response.data) { throw new Error(`HTTP error! status: ${response.status}`); } return response.data; } catch (error) { logger.error("Error making Onyx request:", error); return null; } } async function makeOnyxRequestStream(url, body) { const headers = { "Content-Type": "application/json", }; try { const response = await axios.post(url, body, { headers }); if (!response.data) { throw new Error(`HTTP error! status: ${response.status}`); } const res = magicConvert(response.data); return res; } catch (error) { logger.error("Error making Onyx request:", error); return null; } } const magicConvert = (data) => { try { return JSON.parse(data); } catch (error) { return JSON.parse(data.split(`{"agentic_message_ids": []}`)?.[1]); } }; // Format send message response data function formatSendMessageResponse(response) { const messageContent = response.message || "No message content"; const queryInfo = response.rephrased_query ? `Query: ${response.rephrased_query}` : ""; const messageInfo = `Message ID: ${response.message_id}`; let docsInfo = ""; if (response.context_docs && response.context_docs.top_documents.length > 0) { const topDoc = response.context_docs.top_documents[0]; docsInfo = [ `Top source: ${topDoc.semantic_identifier || "Unknown"}`, `Relevance: ${topDoc.score.toFixed(2) || "Unknown"}`, `Link: ${topDoc.link || "No link available"}`, ].join("\n"); } return [ messageInfo, queryInfo, "---", messageContent, "---", docsInfo ? `Sources:\n${docsInfo}` : "", ] .filter(Boolean) .join("\n"); } // Initialize MCP server const server = new McpServer({ name: "context-bank", version: "1.0.0", }); // curl -X POST "http://172.30.22.52:3000/api/chat/document-search" -H "Content-Type: application/json" -d '{"message": "Tìm kiếm tài liệu về Sipher game 1", "search_type": "semantic", "retrieval_options": { "enable_auto_detect_filters": false, "offset": 0, "limit": 3, "dedupe_docs": true}, "evaluation_type": "skip", "chunks_above": 1, "chunks_below": 1, "full_doc": false}' | jq server.tool("document-search", "Search for documents in the AtherOS's knowledge base", { message: z.string().describe("message to search for"), }, async ({ message }) => { const searchUrl = `${ONYX_API_BASE}/api/chat/document-search`; const body = { message: message, search_type: "semantic", retrieval_options: { enable_auto_detect_filters: false, offset: 0, limit: 3, dedupe_docs: true, }, evaluation_type: "skip", chunks_above: 1, chunks_below: 1, full_doc: false, }; const documentSearchResponse = await makeOnyxRequest(searchUrl, body); if (!documentSearchResponse) { return { content: [ { type: "text", text: `Failed to search for documents in the AtherOS's knowledge base`, }, ], }; } return { content: documentSearchResponse?.top_documents?.map((doc) => ({ type: "text", text: doc.content + "\n" + doc.link, })) ?? [ { type: "text", text: `No documents found in the AtherOS's knowledge base`, }, ], }; }); // server.tool( // "create-chat-session", // "Create a chat session for querying the AtherOS's knowledge base", // { // persona_id: z.number().optional().describe("user id, default is 0"), // description: z // .string() // .optional() // .describe("description of the chat session, default is empty string"), // }, // async ({ // persona_id, // description, // }: { // persona_id?: number; // description?: string; // }) => { // const createChatSessionUrl = `${ONYX_API_BASE}/api/chat/create-chat-session`; // const body: CreateChatSessionRequest = { // persona_id: persona_id ?? 0, // description: description ?? "", // }; // const createChatSessionData = // await makeOnyxRequest<CreateChatSessionResponse>( // createChatSessionUrl, // body, // ); // if (!createChatSessionData) { // return { // content: [ // { // type: "text", // text: `Failed to create chat session for querying the AtherOS's knowledge base`, // }, // ], // }; // } // const chat_session_id = createChatSessionData.chat_session_id; // if (!chat_session_id) { // return { // content: [ // { // type: "text", // text: "Failed to get chat session id", // }, // ], // }; // } // const chatSessionText = `Chat session created for querying the AtherOS's knowledge base. Chat session id: ${chat_session_id}`; // return { // content: [ // { // type: "text", // text: chatSessionText, // }, // ], // }; // }, // ); // server.tool( // "query-atheros", // "Send a message to the chat session for querying the AtherOS's knowledge base", // { // chat_session_id: z.string().describe("chat session id"), // message: z // .string() // .describe("message to send for querying the knowledge base"), // parent_message_id: z // .number() // .optional() // .describe( // "parent message id, if the message is a reply to a previous message, if not provided, use undefined", // ), // }, // async ({ // chat_session_id, // message, // parent_message_id, // }: { // chat_session_id: string; // message: string; // parent_message_id?: number; // }) => { // const sendMessageUrl = `${ONYX_API_BASE}/api/chat/send-message`; // const body: SendMessageRequest = { // alternate_assistant_id: 0, // chat_session_id: chat_session_id, // message: message, // prompt_id: 0, // search_doc_ids: null, // file_descriptors: [], // regenerate: false, // retrieval_options: { // run_search: "auto", // real_time: true, // filters: { // source_type: null, // document_set: null, // time_cutoff: null, // tags: [], // }, // }, // prompt_override: null, // llm_override: { // model_provider: "Default", // model_version: "gpt-4o", // }, // use_agentic_search: false, // parent_message_id: parent_message_id ?? null, // }; // const sendMessageResponse = await makeOnyxRequestStream<any>( // sendMessageUrl, // body, // ); // if (!sendMessageResponse) { // return { // content: [ // { // type: "text", // text: `Failed to send message ${message} to chat session ${chat_session_id}`, // }, // ], // }; // } // const messageResponse = sendMessageResponse.message; // if (!messageResponse) { // return { // content: [ // { // type: "text", // text: `Failed to get message response from chat session ${chat_session_id}`, // }, // ], // }; // } // const messageResponseText = formatSendMessageResponse(sendMessageResponse); // return { // content: [ // { // type: "text", // text: messageResponseText, // }, // ], // }; // }, // ); // Start the server async function main() { const transport = new StdioServerTransport(); await server.connect(transport); logger.info("Context Bank MCP Server running on stdio"); } main().catch((error) => { logger.error("Fatal error in main():", error); process.exit(1); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/vulh1209/context-bank-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server