UNPKG

@veas/protocol

Version:

Universal protocol for knowledge management and project tracking systems - enabling seamless interoperability between platforms and AI assistants

125 lines (103 loc) 3 kB
/** * MCP Client for communicating with MCP servers */ import type { AuthContext } from '../../protocols/common/index.js' export interface MCPRequest { jsonrpc: '2.0' method: string params: any id: string | number } export interface MCPResponse { jsonrpc: '2.0' result?: any error?: MCPError id: string | number } export interface MCPError { code: number message: string data?: any } export interface MCPClientConfig { endpoint: string headers?: Record<string, string> } export class MCPClient { private requestId = 1 constructor(private config: MCPClientConfig) { if (!config || !config.endpoint) { throw new Error('Endpoint is required') } } async callTool(toolName: string, args: any, authContext?: AuthContext): Promise<any> { const request: MCPRequest = { jsonrpc: '2.0', method: 'tools/call', params: { name: toolName, ...(args !== undefined && Object.keys(args).length > 0 ? { arguments: args } : {}), }, id: this.requestId++, } const headers: Record<string, string> = { 'Content-Type': 'application/json', ...this.config.headers, } if (authContext) { headers['X-User-Id'] = authContext.userId headers['X-Scopes'] = authContext.scopes.join(',') } const response = await (globalThis.fetch || fetch)(this.config.endpoint, { method: 'POST', headers, body: JSON.stringify(request), }) if (!response.ok) { throw new Error(`MCP request failed: ${response.statusText}`) } const result = await response.json() as MCPResponse if (result.error) { throw new Error(`MCP error ${result.error.code}: ${result.error.message}`) } // Extract data from MCP response format if (result.result?.content?.[0]) { const content = result.result.content[0] if (content.type === 'json' && content.data) { return content.data } else if (content.type === 'text' && content.text) { // Try to parse as JSON if possible try { return JSON.parse(content.text) } catch { return content.text } } } return result.result } async listTools(): Promise<any[]> { const request: MCPRequest = { jsonrpc: '2.0', method: 'tools/list', params: {}, id: this.requestId++, } const response = await (globalThis.fetch || fetch)(this.config.endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', ...this.config.headers, }, body: JSON.stringify(request), }) if (!response.ok) { throw new Error(`MCP request failed: ${response.statusText}`) } const result = await response.json() as MCPResponse if (result.error) { throw new Error(`MCP error ${result.error.code}: ${result.error.message}`) } return result.result?.tools || [] } }