UNPKG

octagon-13f-holdings-mcp

Version:

MCP server for 13F Holdings Analysis. Provides specialized AI-powered institutional ownership and holdings data analysis with comprehensive Form 13F filings, fund performance analytics, and industry-level holdings insights.

115 lines (114 loc) 5.75 kB
#!/usr/bin/env node 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-13f-holdings-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"), }); // Holdings Agent server.tool("octagon-holdings-agent", "[PUBLIC MARKET INTELLIGENCE] Specialized agent for institutional ownership and holdings data, providing comprehensive insights into Form 13F filings, institutional investor activity, fund performance, and industry-level holdings analytics. Capabilities: Retrieve the latest Form 13F and related institutional ownership filings; Analyze institutional holder filings for specific securities and periods; Summarize performance of institutional holders (funds, asset managers); Break down institutional portfolios by industry/sector; Summarize institutional positions for a given security; Benchmark industry performance based on institutional holdings. Use Cases: Tracking institutional buying and selling activity for specific stocks; Analyzing fund manager performance and portfolio allocation; Benchmarking industry and sector performance based on institutional holdings; Identifying new or exited positions by major funds; Understanding industry exposure and concentration in institutional portfolios. Example queries: '@octagon-holdings-agent Retrieve the most recent Form 13F and related filings submitted by institutional investors, limited to 50 records on page 0.'; '@octagon-holdings-agent Retrieve analytics for institutional holder filings for AAPL in Q2 of 2023, limited to 20 records on page 0.'; '@octagon-holdings-agent Get a summary of the performance of the institutional holder with CIK 0001166559.'; '@octagon-holdings-agent Retrieve the industry breakdown for the holder with CIK 0001067983 for Q4 of 2024.'; '@octagon-holdings-agent Get a summary of institutional positions for AAPL for Q4 of 2024.'; '@octagon-holdings-agent Get a financial performance summary for all industries for Q4 of 2024.'", { 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-holdings-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 Holdings agent:", error); return { isError: true, content: [ { type: "text", text: `Error: Failed to process holdings 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();