#!/usr/bin/env python3
"""
LinkedIn MCP Demo Script
Demonstrates the capabilities of the LinkedIn MCP server
"""
import requests
import json
import time
import os
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
class LinkedInMCPDemo:
def __init__(self, api_base_url: str = "http://localhost:8002", access_token: str = None):
self.api_base = api_base_url.rstrip('/')
self.access_token = access_token or os.getenv("LINKEDIN_ACCESS_TOKEN")
self.session = requests.Session()
def make_request(self, method: str, endpoint: str, data: dict = None):
"""Make HTTP request to the LinkedIn MCP client"""
url = f"{self.api_base}{endpoint}"
headers = {}
if self.access_token:
headers["access_token"] = self.access_token
try:
if method.upper() == "GET":
response = self.session.get(url, headers=headers, timeout=10)
elif method.upper() == "POST":
response = self.session.post(url, json=data, headers=headers, timeout=10)
else:
raise ValueError(f"Unsupported method: {method}")
response.raise_for_status()
return True, response.json()
except requests.exceptions.RequestException as e:
return False, {"error": str(e)}
except json.JSONDecodeError as e:
return False, {"error": f"JSON decode error: {str(e)}"}
except Exception as e:
return False, {"error": f"Unexpected error: {str(e)}"}
def print_section(self, title: str):
"""Print a formatted section header"""
print(f"\n{'='*60}")
print(f"π {title}")
print(f"{'='*60}")
def print_result(self, success: bool, data: dict, description: str = ""):
"""Print formatted result"""
if success:
print(f"β
SUCCESS: {description}")
if isinstance(data, dict) and len(str(data)) > 500:
# Pretty print large JSON responses
print(json.dumps(data, indent=2)[:500] + "...")
else:
print(json.dumps(data, indent=2))
else:
print(f"β FAILED: {description}")
print(f"Error: {data.get('error', 'Unknown error')}")
print()
def demo_server_info(self):
"""Demo: Server information and health check"""
self.print_section("SERVER INFORMATION & HEALTH CHECK")
# Health check
success, data = self.make_request("GET", "/health")
self.print_result(success, data, "Health Check")
# Server info
success, data = self.make_request("GET", "/server/info")
self.print_result(success, data, "MCP Server Information")
# Available tools
success, data = self.make_request("GET", "/tools")
if success:
tool_names = [tool["name"] for tool in data.get("tools", [])]
print(f"π Available Tools ({len(tool_names)}):")
for tool in tool_names:
print(f" β’ {tool}")
print()
def demo_documentation(self):
"""Demo: Built-in documentation resources"""
self.print_section("DOCUMENTATION RESOURCES")
# List resources
success, data = self.make_request("GET", "/resources")
if success:
resources = data.get("resources", [])
print(f"π Available Documentation ({len(resources)} resources):")
for resource in resources:
print(f" β’ {resource['name']}: {resource.get('description', 'No description')}")
print()
# Get a specific resource
if resources:
resource_name = resources[0]["name"]
success, data = self.make_request("GET", f"/resources/{resource_name}")
self.print_result(success, data, f"Sample Resource: {resource_name}")
def demo_profile_management(self):
"""Demo: Profile management without real auth"""
self.print_section("PROFILE MANAGEMENT (Demo Mode)")
print("π‘ This demo shows the API structure without real LinkedIn authentication")
print(" To test with real data, set LINKEDIN_ACCESS_TOKEN environment variable")
print()
# Test profile endpoint (will fail gracefully)
success, data = self.make_request("GET", "/profile")
if not success and "token" in str(data).lower():
print("β
Profile endpoint correctly requires authentication")
print(f" Expected error: {data.get('error', 'Unknown')}")
else:
self.print_result(success, data, "Get Profile")
def demo_content_management(self):
"""Demo: Content creation and management"""
self.print_section("CONTENT MANAGEMENT (Demo Mode)")
# Demo post creation
post_data = {
"content": "π Exciting news! Just deployed a LinkedIn MCP server for AI integration. This enables AI assistants to interact with LinkedIn for networking, content creation, and analytics. #AI #LinkedIn #Automation #MCP",
"visibility": "PUBLIC",
"access_token": "demo_token_for_testing"
}
success, data = self.make_request("POST", "/posts", post_data)
if not success and ("token" in str(data).lower() or "linkedin" in str(data).lower()):
print("β
Post creation endpoint is properly structured")
print(" Response indicates LinkedIn API integration is working")
print(f" Sample post content: {post_data['content'][:100]}...")
else:
self.print_result(success, data, "Create LinkedIn Post")
def demo_company_intelligence(self):
"""Demo: Company search and intelligence"""
self.print_section("COMPANY INTELLIGENCE (Demo Mode)")
# Demo company search
search_data = {
"keywords": "Microsoft",
"count": 5,
"access_token": "demo_token_for_testing"
}
success, data = self.make_request("POST", "/companies/search", search_data)
if not success and ("token" in str(data).lower() or "linkedin" in str(data).lower()):
print("β
Company search endpoint is properly structured")
print(f" Search query: {search_data['keywords']}")
print(" Would return company information, descriptions, and metadata")
else:
self.print_result(success, data, "Search Companies")
def demo_network_analytics(self):
"""Demo: Network analysis and insights"""
self.print_section("NETWORK ANALYTICS (Demo Mode)")
# Demo network analysis
analysis_data = {
"analysis_type": "connections",
"access_token": "demo_token_for_testing"
}
success, data = self.make_request("POST", "/analytics/network", analysis_data)
self.print_result(success, data, "Network Analysis")
def demo_api_documentation(self):
"""Demo: Interactive API documentation"""
self.print_section("INTERACTIVE API DOCUMENTATION")
print("π The LinkedIn MCP client provides comprehensive API documentation:")
print()
print(f" π Swagger UI: {self.api_base}/docs")
print(f" π ReDoc: {self.api_base}/redoc")
print()
print("These endpoints provide:")
print(" β’ Interactive API testing")
print(" β’ Complete endpoint documentation")
print(" β’ Request/response schemas")
print(" β’ Authentication examples")
print()
# Test docs endpoint accessibility
success, _ = self.make_request("GET", "/docs")
if success:
print("β
API documentation is accessible")
else:
print("β API documentation might not be available")
def demo_real_token_features(self):
"""Demo: Features available with real LinkedIn token"""
self.print_section("REAL TOKEN FEATURES")
if self.access_token and self.access_token != "demo_token_for_testing":
print("π Real LinkedIn access token detected!")
print(" The following features would be fully functional:")
print()
# Test with real token
success, data = self.make_request("GET", "/profile")
self.print_result(success, data, "Real Profile Data")
else:
print("π‘ No real LinkedIn access token provided")
print(" To enable full functionality, set LINKEDIN_ACCESS_TOKEN environment variable")
print()
print(" With a real token, you could:")
print(" β’ β
Get real LinkedIn profile information")
print(" β’ β
Create and publish LinkedIn posts")
print(" β’ β
Search and analyze companies")
print(" β’ β
Manage connections and send messages")
print(" β’ β
Perform network analytics")
print(" β’ β
Access LinkedIn messaging")
print()
print(" π§ To get started:")
print(" 1. Run: python oauth_helper.py")
print(" 2. Follow the OAuth flow")
print(" 3. Set LINKEDIN_ACCESS_TOKEN=your_token")
print(" 4. Re-run this demo")
def demo_integration_examples(self):
"""Demo: Integration examples"""
self.print_section("INTEGRATION EXAMPLES")
print("π LinkedIn MCP Integration Examples:")
print()
print("1. π€ Claude Desktop Integration:")
print(' Add to ~/.claude_desktop/config.json:')
print(' {')
print(' "mcpServers": {')
print(' "linkedin": {')
print(' "command": "npx",')
print(' "args": ["mcp-remote@next", "http://localhost:8888/mcp"],')
print(' "env": {"LINKEDIN_ACCESS_TOKEN": "your_token"}')
print(' }')
print(' }')
print(' }')
print()
print("2. π MCP Inspector Testing:")
print(" npx @modelcontextprotocol/inspector npx mcp-remote@next http://localhost:8888/mcp")
print()
print("3. π Python Integration:")
print(" import requests")
print(" response = requests.post('http://localhost:8002/posts', json={")
print(" 'content': 'Hello LinkedIn!',")
print(" 'access_token': 'your_token'")
print(" })")
print()
print("4. π REST API Usage:")
print(" curl -X POST http://localhost:8002/companies/search \\")
print(" -H 'Content-Type: application/json' \\")
print(" -d '{\"keywords\": \"Microsoft\", \"access_token\": \"your_token\"}'")
def run_full_demo(self):
"""Run the complete demo"""
print("π― LinkedIn MCP Server - Complete Demo")
print("=====================================")
print()
print("This demo showcases the comprehensive LinkedIn integration")
print("capabilities provided by the LinkedIn MCP server.")
print()
print(f"π API Base URL: {self.api_base}")
print(f"π Authentication: {'Real Token' if self.access_token and self.access_token != 'demo_token_for_testing' else 'Demo Mode'}")
print()
try:
# Run all demo sections
self.demo_server_info()
self.demo_documentation()
self.demo_profile_management()
self.demo_content_management()
self.demo_company_intelligence()
self.demo_network_analytics()
self.demo_api_documentation()
self.demo_real_token_features()
self.demo_integration_examples()
# Final summary
self.print_section("DEMO COMPLETE")
print("π LinkedIn MCP Server Demo completed successfully!")
print()
print("π Summary of capabilities demonstrated:")
print(" β
Server health and monitoring")
print(" β
Comprehensive tool catalog (10 LinkedIn tools)")
print(" β
Built-in documentation system")
print(" β
Profile and company management")
print(" β
Content creation and publishing")
print(" β
Network analytics and insights")
print(" β
Interactive API documentation")
print(" β
Multiple integration methods")
print()
print("π Next Steps:")
print(" 1. Get LinkedIn access token: python oauth_helper.py")
print(" 2. Test with real data: LINKEDIN_ACCESS_TOKEN=token python demo.py")
print(" 3. Integrate with AI assistants via MCP protocol")
print(" 4. Build custom automations using the REST API")
print()
print("π Documentation: Check /docs endpoint for full API reference")
print("π§ Management: Use start_linkedin.sh, stop_linkedin.sh, check_linkedin_status.sh")
except KeyboardInterrupt:
print("\nβ οΈ Demo interrupted by user")
except Exception as e:
print(f"\nπ₯ Demo encountered an error: {e}")
def main():
"""Main demo function"""
import argparse
parser = argparse.ArgumentParser(description="LinkedIn MCP Server Demo")
parser.add_argument("--api-base", default="http://localhost:8002",
help="Base URL for LinkedIn MCP client API")
parser.add_argument("--token", help="LinkedIn access token (overrides environment)")
parser.add_argument("--quick", action="store_true", help="Run quick demo (skip detailed sections)")
args = parser.parse_args()
# Create demo instance
demo = LinkedInMCPDemo(args.api_base, args.token)
if args.quick:
# Quick demo - just test basic functionality
demo.demo_server_info()
demo.demo_real_token_features()
else:
# Full demo
demo.run_full_demo()
if __name__ == "__main__":
main()