UNPKG

@gongrzhe/langflow-doc-qa-server

Version:

A Model Context Protocol server for document Q&A powered by Langflow

107 lines (106 loc) 4.41 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from '@modelcontextprotocol/sdk/types.js'; import axios from 'axios'; // Get API endpoint from command line argument const apiEndpoint = process.argv[2] || process.env.API_ENDPOINT; if (!apiEndpoint) { console.error('Error: API endpoint must be provided as an argument or via API_ENDPOINT environment variable'); process.exit(1); } class DocQAServer { server; apiEndpoint; constructor(apiEndpoint) { this.apiEndpoint = apiEndpoint; this.server = new Server({ name: '@gongrzhe/langflow-doc-qa-server', version: '1.0.1', }, { capabilities: { tools: {}, }, }); this.setupToolHandlers(); this.server.onerror = (error) => console.error('[MCP Error]', error); process.on('SIGINT', async () => { await this.server.close(); process.exit(0); }); } setupToolHandlers() { this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: 'query_docs', description: 'Query the document Q&A system with a prompt', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'The query prompt to search for in the documents', }, }, required: ['query'], }, }, ], })); this.server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name !== 'query_docs') { throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`); } const { query } = request.params.arguments; try { console.error(`Sending request to ${this.apiEndpoint}`); const response = await axios.post(this.apiEndpoint, { input_value: query, output_type: 'chat', input_type: 'chat' }, { headers: { 'Content-Type': 'application/json', }, params: { stream: false, }, timeout: 30000, // 30 seconds timeout }); if (!response.data?.outputs?.[0]?.outputs?.[0]?.results?.message?.text) { console.error('Unexpected response format:', JSON.stringify(response.data, null, 2)); throw new McpError(ErrorCode.InternalError, 'Unexpected response format from Langflow API'); } const result = response.data.outputs[0].outputs[0].results.message.text; return { content: [ { type: 'text', text: result, }, ], }; } catch (error) { if (axios.isAxiosError(error)) { console.error('API request failed:', { status: error.response?.status, data: error.response?.data, message: error.message }); throw new McpError(ErrorCode.InternalError, `API request failed: ${error.message}. Status: ${error.response?.status}. Data: ${JSON.stringify(error.response?.data)}`); } console.error('Unknown error:', error); throw error; } }); } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error(`Langflow Document Q&A MCP server running on stdio, using API endpoint: ${this.apiEndpoint}`); } } const server = new DocQAServer(apiEndpoint); server.run().catch(console.error);