octagon-transcripts-mcp
Version:
MCP server for Earnings Call Transcripts Analysis. Provides specialized AI-powered earnings call transcript analysis with over 8,000 public companies coverage and historical data dating back to 2018.
115 lines (114 loc) • 4.88 kB
JavaScript
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import dotenv from "dotenv";
import { readFile } from "fs/promises";
import OpenAI from "openai";
import path from "path";
import { fileURLToPath } from "url";
import { z } from "zod";
// Get package.json info
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const packageJsonPath = path.join(__dirname, "..", "package.json");
const packageJsonContent = await readFile(packageJsonPath, "utf8");
const packageInfo = JSON.parse(packageJsonContent);
// Load environment variables
dotenv.config();
// Check for required environment variables
const OCTAGON_API_KEY = process.env.OCTAGON_API_KEY;
const OCTAGON_API_BASE_URL = process.env.OCTAGON_API_BASE_URL || "https://api.octagonagents.com/v1";
if (!OCTAGON_API_KEY) {
console.error("Error: OCTAGON_API_KEY is not set in the environment variables");
console.error("Please set the OCTAGON_API_KEY environment variable or use 'env OCTAGON_API_KEY=your_key npx -y octagon-transcripts-mcp'");
process.exit(1);
}
// Initialize OpenAI client with Octagon API
const octagonClient = new OpenAI({
apiKey: OCTAGON_API_KEY,
baseURL: OCTAGON_API_BASE_URL,
defaultHeaders: {
"User-Agent": `${packageInfo.name}/${packageInfo.version} (Node.js/${process.versions.node})`
},
});
// Create MCP server
const server = new McpServer({
name: packageInfo.name,
version: packageInfo.version,
});
// Helper function to process streaming responses
async function processStreamingResponse(stream) {
let fullResponse = "";
let citations = [];
try {
// Process the streaming response
for await (const chunk of stream) {
// For Chat Completions API
if (chunk.choices && chunk.choices[0]?.delta?.content) {
fullResponse += chunk.choices[0].delta.content;
// Check for citations in the final chunk
if (chunk.choices[0]?.finish_reason === "stop" && chunk.choices[0]?.citations) {
citations = chunk.choices[0].citations;
}
}
// For Responses API
if (chunk.type === "response.output_text.delta") {
fullResponse += chunk.text?.delta || "";
}
}
return fullResponse;
}
catch (error) {
console.error("Error processing streaming response:", error);
throw error;
}
}
// Define a schema for the 'prompt' parameter that all tools will use
const promptSchema = z.object({
prompt: z.string().describe("Your natural language query or request for the agent"),
});
// Earnings Call Transcripts Agent
server.tool("octagon-transcripts-agent", "[PUBLIC MARKET INTELLIGENCE] A specialized agent for analyzing earnings call transcripts and management commentary. Covers over 8,000 public companies with continuous daily updates for real-time insights. Historical data dating back to 2018 enables robust time-series analysis. Extract information from earnings call transcripts, including executive statements, financial guidance, analyst questions, and forward-looking statements. Best for analyzing management sentiment, extracting guidance figures, and identifying key business trends. Example queries: 'What did Amazon's CEO say about AWS growth expectations in the latest earnings call?', 'Summarize key financial metrics mentioned in Tesla's Q2 2023 earnings call', 'What questions did analysts ask about margins during Netflix's latest earnings call?'.", {
prompt: z.string().describe("Your natural language query or request for the agent"),
}, async ({ prompt }) => {
try {
const response = await octagonClient.chat.completions.create({
model: "octagon-transcripts-agent",
messages: [{ role: "user", content: prompt }],
stream: true,
metadata: { tool: "mcp" }
});
const result = await processStreamingResponse(response);
return {
content: [
{
type: "text",
text: result,
},
],
};
}
catch (error) {
console.error("Error calling Transcripts agent:", error);
return {
isError: true,
content: [
{
type: "text",
text: `Error: Failed to process earnings call transcript query. ${error}`,
},
],
};
}
});
// Start the server with stdio transport
async function main() {
try {
const transport = new StdioServerTransport();
await server.connect(transport);
}
catch (error) {
process.exit(1);
}
}
main();