Skip to main content
Glama
ertiqah
by ertiqah

analyze_linkedin_chat

Analyze LinkedIn profiles, content, and network data through conversational queries to extract insights and answer questions about professional connections and activities.

Instructions

Ask questions about the user's LinkedIn profile, content, or network, with support for multi-turn conversations.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesThe question or request about LinkedIn data to be analyzed.
conversation_historyNoOptional. Previous messages in the conversation for context. Each message must have 'role' (user/assistant) and 'content' (text).

Implementation Reference

  • cli.js:424-511 (handler)
    Handler implementation for the 'analyze_linkedin_chat' tool. Validates 'query' (required string) and 'conversation_history' (optional array of messages), proxies the request to the backend API endpoint, and returns the reply text or an error message.
    } else if (name === 'analyze_linkedin_chat') {
        console.error(`${packageName}: Received call for analyze_linkedin_chat tool.`);
        const apiKey = process.env.LINKEDIN_MCP_API_KEY;
        const query = args?.query;
        const conversationHistory = args?.conversation_history || [];
    
        if (!apiKey) {
            sendResponse({ jsonrpc: "2.0", error: { code: -32001, message: "Server Configuration Error: API Key not set." }, id });
            return;
        }
        if (typeof query !== 'string' || query.trim() === '') {
            sendResponse({ jsonrpc: "2.0", error: { code: -32602, message: "Invalid arguments: 'query' (string) required." }, id });
            return;
        }
        if (!Array.isArray(conversationHistory)) {
            sendResponse({ jsonrpc: "2.0", error: { code: -32602, message: "Invalid arguments: 'conversation_history' must be an array." }, id });
            return;
        }
    
        try {
            const headers = { "Authorization": `Bearer ${apiKey}`, "Content-Type": "application/json", "Accept": "application/json" };
            const payload = { 
              "query": query,
              "conversation_history": conversationHistory
            };
            console.error(`${packageName}: Calling analyze chat API: ${backendAnalyzeChatApiUrl} with payload:`, JSON.stringify(payload, null, 2));
            const apiResponse = await axios.post(backendAnalyzeChatApiUrl, payload, { headers, timeout: 60000 });
            console.error(`${packageName}: Analyze chat API response status: ${apiResponse.status}`);
            console.error(`${packageName}: Analyze chat API response data:`, JSON.stringify(apiResponse.data, null, 2));
    
            if (apiResponse.data && apiResponse.data.reply) {
                sendResponse({ 
                  jsonrpc: "2.0", 
                  result: { 
                    content: [
                      {
                        type: "text",
                        text: apiResponse.data.reply
                      }
                    ],
                    isError: false
                  }, 
                  id 
                });
            } else {
                const errorMessage = apiResponse.data?.error || "Backend API Error (no detail)";
                console.error(`${packageName}: Analyze chat API Error: ${errorMessage}`);
                sendResponse({ 
                  jsonrpc: "2.0", 
                  result: {
                    content: [
                      {
                        type: "text",
                        text: `Failed to analyze LinkedIn chat: ${errorMessage}`
                      }
                    ],
                    isError: true
                  }, 
                  id 
                });
            }
    
        } catch (error) {
            let errorMessage = `Failed to call analyze chat API: ${error.message}`;
            if (error.response) {
                // Extract the error message directly from the backend response
                const backendError = error.response.data?.error || error.response.data?.message;
                errorMessage = backendError || `Backend API Error (Status ${error.response.status})`;
                console.error(`${packageName}: Analyze chat API Error Response:`, error.response.data); 
            } else if (error.request) {
                errorMessage = "No response received from analyze chat API.";
            }
            console.error(`${packageName}: ${errorMessage}`);
            
            sendResponse({ 
              jsonrpc: "2.0", 
              result: { 
                content: [
                  {
                    type: "text",
                    text: `Failed to analyze LinkedIn chat: ${errorMessage}`
                  }
                ],
                isError: true
              }, 
              id 
            });
        }
  • Input schema definition for the 'analyze_linkedin_chat' tool, defining the expected parameters: required 'query' string and optional 'conversation_history' array of role/content objects.
        name: "analyze_linkedin_chat",
        description: "Ask questions about the user's LinkedIn profile, content, or network, with support for multi-turn conversations.",
        inputSchema: {
            type: "object",
            properties: {
                query: {
                    type: "string",
                    description: "The question or request about LinkedIn data to be analyzed."
                },
                conversation_history: {
                    type: "array",
                    description: "Optional. Previous messages in the conversation for context. Each message must have 'role' (user/assistant) and 'content' (text).",
                    items: {
                        type: "object",
                        properties: {
                            role: {
                                type: "string",
                                description: "The sender of the message: 'user' or 'assistant'."
                            },
                            content: {
                                type: "string",
                                description: "The text content of the message."
                            }
                        },
                        required: ["role", "content"]
                    }
                }
            },
            required: ["query"]
        }
    },
  • cli.js:1181-1373 (registration)
    The tool is registered by being included in the 'tools/list' response, which lists all available tools with their schemas.
    if (method === 'tools/list') {
        console.error(`${packageName}: Received tools/list request, sending known tool.`);
        sendResponse({
            jsonrpc: "2.0",
            id: id,
            result: {
                tools: [
                    {
                        name: "publish_linkedin_post",
                        description: "Publish a text post to LinkedIn, optionally including media (images/videos) specified by URL.",
                        inputSchema: {
                            type: "object",
                            properties: {
                                post_text: {
                                    type: "string",
                                    description: "The text content of the LinkedIn post."
                                },
                                media: {
                                    type: "array",
                                    description: "Optional. A list of media items to attach to the post. Each item must have a 'file_url' pointing to a direct image or video URL and a 'filename'.",
                                    items: {
                                        type: "object",
                                        properties: {
                                            file_url: {
                                                type: "string",
                                                description: "A direct URL to the image or video file (e.g., ending in .jpg, .png, .mp4)."
                                            },
                                            filename: {
                                                type: "string",
                                                description: "A filename for the media item (e.g., 'promo_video.mp4')."
                                            }
                                        },
                                        required: ["file_url", "filename"]
                                    }
                                }
                            },
                            required: ["post_text"]
                        }
                    },
                    {
                        name: "schedule_linkedin_post",
                        description: "Schedule a text post for LinkedIn at a specific future date and time, optionally including media (images/videos) specified by URL.",
                        inputSchema: {
                            type: "object",
                            properties: {
                                post_text: {
                                    type: "string",
                                    description: "The text content of the LinkedIn post to be scheduled."
                                },
                                scheduled_date: {
                                    type: "string",
                                    description: "The date and time to publish the post, in ISO 8601 format (e.g., '2025-12-31T10:00:00Z' or '2025-12-31T15:30:00+05:30'). Must be in the future."
                                },
                                media: {
                                    type: "array",
                                    description: "Optional. A list of media items to attach to the post. Each item must have a 'file_url' pointing to a direct image or video URL and a 'filename'.",
                                    items: {
                                        type: "object",
                                        properties: {
                                            file_url: {
                                                type: "string",
                                                description: "A direct URL to the image or video file (e.g., ending in .jpg, .png, .mp4)."
                                            },
                                            filename: {
                                                type: "string",
                                                description: "A filename for the media item (e.g., 'meeting_notes.mp4')."
                                            }
                                        },
                                        required: ["file_url", "filename"]
                                    }
                                }
                            },
                            required: ["post_text", "scheduled_date"]
                        }
                    },
                    {
                        name: "publish_twitter_post",
                        description: "Publish a text post (tweet) to Twitter.",
                        inputSchema: {
                            type: "object",
                            properties: {
                                post_text: {
                                    type: "string",
                                    description: "The text content of the tweet (maximum 280 characters)."
                                }
                            },
                            required: ["post_text"]
                        }
                    },
                    {
                        name: "analyze_linkedin_chat",
                        description: "Ask questions about the user's LinkedIn profile, content, or network, with support for multi-turn conversations.",
                        inputSchema: {
                            type: "object",
                            properties: {
                                query: {
                                    type: "string",
                                    description: "The question or request about LinkedIn data to be analyzed."
                                },
                                conversation_history: {
                                    type: "array",
                                    description: "Optional. Previous messages in the conversation for context. Each message must have 'role' (user/assistant) and 'content' (text).",
                                    items: {
                                        type: "object",
                                        properties: {
                                            role: {
                                                type: "string",
                                                description: "The sender of the message: 'user' or 'assistant'."
                                            },
                                            content: {
                                                type: "string",
                                                description: "The text content of the message."
                                            }
                                        },
                                        required: ["role", "content"]
                                    }
                                }
                            },
                            required: ["query"]
                        }
                    },
                    {
                        name: "generate_linkedin_post",
                        description: "Generate three LinkedIn post variants from any content (article, newsletter, notes, etc.) to optimize engagement.",
                        inputSchema: {
                            type: "object",
                            properties: {
                                content: {
                                    type: "string",
                                    description: "The source content to transform into LinkedIn posts. Can be articles, emails, newsletters, notes, etc."
                                },
                                content_type: {
                                    type: "string",
                                    description: "Optional. A short description of the content type (e.g., 'article', 'newsletter', 'notes'). Defaults to 'article'."
                                }
                            },
                            required: ["content"]
                        }
                    },
                    {
                        name: "get_linkedin_posts",
                        description: "Retrieve the user's recent LinkedIn posts with engagement metrics.",
                        inputSchema: {
                            type: "object",
                            properties: {
                                limit: {
                                    type: "number",
                                    description: "Optional. Number of posts to retrieve (1-20). Defaults to 5."
                                }
                            }
                        }
                    },
                    {
                        name: "get_linkedin_profile",
                        description: "Retrieve the user's LinkedIn profile information including headline, summary, experience, and education.",
                        inputSchema: {
                            type: "object",
                            properties: {}
                        }
                    },
                    {
                        name: "set_linkedin_url",
                        description: "Set or update the LinkedIn profile URL to analyze. Required before using profile/posts retrieval tools if not set previously.",
                        inputSchema: {
                            type: "object",
                            properties: {
                                linkedin_url: {
                                    type: "string",
                                    description: "The full LinkedIn profile URL (e.g., https://www.linkedin.com/in/username/)"
                                }
                            },
                            required: ["linkedin_url"]
                        }
                    },
                    {
                        name: "refresh_linkedin_profile",
                        description: "Force a refresh of the LinkedIn profile data to update any recent changes.",
                        inputSchema: {
                            type: "object",
                            properties: {}
                        }
                    },
                    {
                        name: "refresh_linkedin_posts",
                        description: "Force a refresh of LinkedIn posts data to capture recently published content.",
                        inputSchema: {
                            type: "object",
                            properties: {}
                        }
                    }
                ]
            }
        });
  • cli.js:14-14 (helper)
    Backend API endpoint URL used by the analyze_linkedin_chat handler.
    const backendAnalyzeChatApiUrl = 'https://ligo.ertiqah.com/api/mcp/analyze-linkedin-chat';
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It mentions 'multi-turn conversations' and 'support for multi-turn conversations', which adds some behavioral context about conversation handling. However, it fails to disclose critical traits: whether this is a read-only or mutative operation, authentication needs, rate limits, error handling, or what the output looks like (e.g., structured analysis vs. raw data). For a tool with no annotations, this leaves significant gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, well-structured sentence that front-loads the core purpose ('Ask questions about LinkedIn data') and adds a key feature ('multi-turn conversations'). It avoids redundancy and wastes no words, though it could be slightly more detailed given the lack of annotations. Every part earns its place, making it efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no annotations and no output schema, the description is incomplete for a tool with 2 parameters and behavioral complexity. It covers the basic purpose and hints at conversation support but omits essential details: output format (critical since no output schema), mutation vs. read-only status, error conditions, and integration with sibling tools. For a conversational analysis tool, this leaves too much undefined for reliable agent use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, providing clear documentation for both parameters ('query' and 'conversation_history'). The description adds minimal value beyond the schema: it implies 'query' is for 'questions about LinkedIn data' and 'conversation_history' enables 'multi-turn conversations', but doesn't elaborate on syntax, formats, or examples. With high schema coverage, the baseline score of 3 is appropriate as the description doesn't significantly enhance parameter understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Ask questions about the user's LinkedIn profile, content, or network' with the verb 'ask questions' and resource 'LinkedIn data'. It distinguishes from siblings like 'get_linkedin_profile' (which likely retrieves raw data) by emphasizing conversational analysis, though it doesn't explicitly name alternatives. The mention of 'multi-turn conversations' adds specificity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context ('Ask questions about LinkedIn data') and hints at when to use it via 'multi-turn conversations', suggesting it's for interactive queries rather than one-off data retrieval. However, it lacks explicit guidance on when to choose this over siblings like 'get_linkedin_profile' or 'analyze_linkedin_chat' vs. other tools, and no exclusions are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ertiqah/linkedin-mcp-runner'

If you have feedback or need assistance with the MCP directory API, please join our Discord server