EnrichB2B MCP Server

by moonlabsai
Verified
""" MCP Server Template with OpenAI, Anthropic, and EnrichB2B integration. """ import os from contextlib import asynccontextmanager from dataclasses import dataclass from typing import AsyncIterator import sys from dotenv import load_dotenv from mcp.server.fastmcp import FastMCP, Context from openai import OpenAI from anthropic import Anthropic from enrichb2b import EnrichB2BConfig, EnrichB2BClient, ContactRequest, ContactActivitiesRequest # Load environment variables load_dotenv() # Initialize API clients openai_client = OpenAI() anthropic_client = Anthropic() enrichb2b_config = EnrichB2BConfig(os.getenv("ENRICHB2B_API_KEY", "")) enrichb2b_client = EnrichB2BClient(enrichb2b_config) @dataclass class AppContext: """Application context with API clients""" openai: OpenAI anthropic: Anthropic enrichb2b: EnrichB2BClient @asynccontextmanager async def app_lifespan(server: FastMCP) -> AsyncIterator[AppContext]: """Manage application lifecycle with type-safe context""" print("Starting MCP server...", file=sys.stderr) try: print("Initializing API clients...", file=sys.stderr) yield AppContext( openai=openai_client, anthropic=anthropic_client, enrichb2b=enrichb2b_client ) print("API clients initialized successfully", file=sys.stderr) except Exception as e: print(f"Error during initialization: {str(e)}", file=sys.stderr) raise finally: print("Shutting down MCP server...", file=sys.stderr) # Create MCP server with dependencies mcp = FastMCP( "LinkedIn Research", dependencies=["openai", "anthropic", "enrichb2b"], description="A server for LinkedIn research and analysis", lifespan=app_lifespan ) @mcp.resource("profile://{linkedin_url}") async def get_profile_resource(linkedin_url: str) -> str: """Get LinkedIn profile data as a resource.""" request = ContactRequest(linkedin_url=linkedin_url) result = enrichb2b_client.search_contact(request) return str(result) @mcp.tool() async def get_profile_details( ctx: Context, linkedin_url: str, include_company_details: bool = True, include_followers_count: bool = True ) -> str: """ Get detailed profile information for a LinkedIn user. Args: linkedin_url: LinkedIn profile URL of the contact include_company_details: Whether to include company information include_followers_count: Whether to include follower count """ enrichb2b = ctx.request_context.lifespan_context.enrichb2b request = ContactRequest(linkedin_url=linkedin_url) ctx.info(f"Fetching profile details for {linkedin_url}") result = enrichb2b.search_contact( request, include_company_details=include_company_details, include_followers_count=include_followers_count ) return str(result) @mcp.tool() async def get_contact_activities( ctx: Context, linkedin_url: str, pages: int = 1, comments_per_post: int = 1 ) -> str: """ Get recent activities and posts from a LinkedIn profile. Args: linkedin_url: LinkedIn profile URL of the contact pages: Number of pages of activities to fetch (1-50) comments_per_post: Number of comment pages per post (0-50) """ enrichb2b = ctx.request_context.lifespan_context.enrichb2b request = ContactActivitiesRequest( linkedin_url=linkedin_url, how_many_pages=pages, how_many_pages_comments_per_post=comments_per_post ) ctx.info(f"Fetching activities for {linkedin_url}") await ctx.report_progress(0, 1) result = enrichb2b.search_contact_activities(request) await ctx.report_progress(1, 1) return str(result) @mcp.prompt() def research_profile(linkedin_url: str) -> str: """Create a prompt for researching a LinkedIn profile.""" return f"""Please research this LinkedIn profile: {linkedin_url} Use the available tools to: 1. Get detailed profile information 2. Analyze their recent activities 3. Summarize key findings about their professional background and engagement""" @mcp.prompt() def analyze_activities(linkedin_url: str) -> str: """Create a prompt for analyzing LinkedIn activities.""" return f"""Please analyze the recent activities of this LinkedIn profile: {linkedin_url} Focus on: 1. Types of content shared 2. Engagement patterns 3. Key topics and interests 4. Professional network interactions""" if __name__ == "__main__": mcp.run()