Model Context Protocol server for LinkedIn integration, enabling authentication and content management through Claude
The LinkedIn MCP server has 4 tools with basic descriptions and Zod schemas, but falls short of production quality on multiple dimensions. All tool descriptions are present but brief (10-60 chars), lacking LLM-optimized context about WHEN to use each tool or prerequisites. Parameter descriptions exist (e.g., 'The text content to post to LinkedIn') but are minimal. No input validation messaging or error recovery guidance. Tool output is unstructured JSON wrapped in text content arrays, not properly documented for downstream chaining. The server uses server-side auth token injection (good), but lacks per-tool permission declarations, error categorization, and idempotence hints on write operations. Naming follows verb_noun convention correctly (linkedin_get_profile, linkedin_post_content) but lacks natural-identifier support, users must authenticate before any tool works, and operations depend on server-side token state rather than accepting user-friendly parameters.
Check if LinkedIn is authenticated. Returns the auth URL if not connected.
Retrieve your 10 most recent LinkedIn posts.
Get your LinkedIn profile info: name, email, picture, and locale.
Post text content to your LinkedIn feed (publicly visible).
Descriptions lack LLM-optimized context. All are under 60 characters and omit WHEN to use each tool or prerequisites (e.g., 'Requires LinkedIn authentication, run linkedin_auth_status first if not connected'). Baseline: A+ tools average 194 chars with clear prerequisites.
No output schema documentation. Tools return responses wrapped in {content: [{type: 'text', text: JSON.stringify(...)}]} but this structure is not documented. LLMs cannot infer what fields are returned by linkedin_get_profile or linkedin_get_my_posts, blocking downstream chaining and forcing the LLM to parse unstructured JSON.
No error categorization or recovery guidance. linkedin_get_profile and others return 'Not authenticated' as plain text. No guidance on what to do next (retry, call linkedin_auth_status, refresh token). Agents cannot distinguish retryable (expired token) from user-fixable (not logged in) from fatal errors.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 51 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 52 | - | v1 |
Destructive operation (linkedin_post_content) lacks confirmation or idempotence hints. No dry-run, no confirmation step, and responses ('Posted successfully!') don't include idempotence identifiers. If an agent retries, duplicates may occur. Destructive tools require tool annotations (destructiveHint: true) and confirmation patterns.
No pagination support for linkedin_get_my_posts. Hardcoded to return 10 posts with no limit/offset parameters. Baseline: paginated tools accept page, limit, and return total_count or next_cursor. If a user has thousands of posts, the agent cannot retrieve beyond the first 10.
No per-tool permission declarations. Tools do not state what OAuth scopes or capabilities they require (e.g., 'w_member_social' for posting). Agents cannot reason about permission constraints or explain to users why a call failed due to insufficient scope.
No audit trail or logging of agent actions. No record of who called what tool, when, and with what parameters (for linkedin_post_content, which makes permanent state changes). Critical for compliance and incident response when agents modify user data.
Input validation is minimal. linkedin_post_content accepts any string for 'text' with no length constraints, character restrictions, or validation messaging. LinkedIn's API has limits (e.g., max post length); oversized inputs fail at API layer with opaque errors instead of failing early with actionable guidance.