Get LinkedIn Post
linkedin_get_postRetrieve a LinkedIn post by its URN, returning post text, author, visibility, and timestamps in markdown or JSON format.
Instructions
Retrieve a LinkedIn post by its URN.
NOTE: Reading posts requires the r_member_social scope for member posts or r_organization_social for org posts. These scopes require LinkedIn approval and are not available to all developers. If you only have w_member_social, use linkedin_create_post and linkedin_list_posts instead.
Requires scope: r_member_social or r_organization_social
Args:
post_urn (string): Post URN (e.g., 'urn:li:share:7123456789')
response_format ('markdown' | 'json'): Output format (default: 'markdown')
Returns: For JSON format: { "id": string, // Post URN "author": string, // Author URN "commentary": string, // Post text "visibility": string, // PUBLIC | CONNECTIONS | LOGGED_IN "lifecycleState": string, // PUBLISHED | DRAFT | DELETED "createdAt": number, // Unix timestamp (ms) "lastModifiedAt": number, "content": object // Media/article content (if any) }
Error Handling:
403 if r_member_social scope is not approved for your app
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| post_urn | Yes | URN of the post to retrieve (e.g., 'urn:li:share:7123456789') | |
| response_format | No | Output format: 'markdown' for human-readable or 'json' for machine-readable | markdown |
Implementation Reference
- src/tools/posts.ts:303-325 (handler)Handler function for linkedin_get_post — fetches a post by URN via REST API and returns markdown or JSON
async (params: GetPostInput) => { try { const post = await restGet<LinkedInPost>( `/posts/${encodeUrn(params.post_urn)}` ); const structured = post as unknown as Record<string, unknown>; if (params.response_format === ResponseFormat.JSON) { return { content: [{ type: "text", text: JSON.stringify(post, null, 2) }], structuredContent: structured, }; } return { content: [{ type: "text", text: formatPost(post) }], structuredContent: structured, }; } catch (error) { return { content: [{ type: "text", text: handleApiError(error) }] }; } } ); - src/tools/posts.ts:61-71 (schema)Zod schema validating input: post_urn (string) and optional response_format (markdown/json)
const GetPostInputSchema = z .object({ post_urn: z .string() .describe("URN of the post to retrieve (e.g., 'urn:li:share:7123456789')"), response_format: z .nativeEnum(ResponseFormat) .default(ResponseFormat.MARKDOWN) .describe("Output format: 'markdown' for human-readable or 'json' for machine-readable"), }) .strict(); - src/tools/posts.ts:262-325 (registration)Registration of linkedin_get_post tool on the MCP server with metadata, schema, annotations, and handler
// Get post server.registerTool( "linkedin_get_post", { title: "Get LinkedIn Post", description: `Retrieve a LinkedIn post by its URN. NOTE: Reading posts requires the r_member_social scope for member posts or r_organization_social for org posts. These scopes require LinkedIn approval and are not available to all developers. If you only have w_member_social, use linkedin_create_post and linkedin_list_posts instead. Requires scope: r_member_social or r_organization_social Args: - post_urn (string): Post URN (e.g., 'urn:li:share:7123456789') - response_format ('markdown' | 'json'): Output format (default: 'markdown') Returns: For JSON format: { "id": string, // Post URN "author": string, // Author URN "commentary": string, // Post text "visibility": string, // PUBLIC | CONNECTIONS | LOGGED_IN "lifecycleState": string, // PUBLISHED | DRAFT | DELETED "createdAt": number, // Unix timestamp (ms) "lastModifiedAt": number, "content": object // Media/article content (if any) } Error Handling: - 403 if r_member_social scope is not approved for your app`, inputSchema: GetPostInputSchema, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true, }, }, async (params: GetPostInput) => { try { const post = await restGet<LinkedInPost>( `/posts/${encodeUrn(params.post_urn)}` ); const structured = post as unknown as Record<string, unknown>; if (params.response_format === ResponseFormat.JSON) { return { content: [{ type: "text", text: JSON.stringify(post, null, 2) }], structuredContent: structured, }; } return { content: [{ type: "text", text: formatPost(post) }], structuredContent: structured, }; } catch (error) { return { content: [{ type: "text", text: handleApiError(error) }] }; } } ); - src/tools/posts.ts:153-166 (helper)Helper function formatPost formats a LinkedInPost object into a human-readable markdown string
function formatPost(post: LinkedInPost): string { const lines: string[] = []; lines.push(`## Post ${post.id}`); lines.push(`- **Author:** ${post.author}`); lines.push(`- **Visibility:** ${post.visibility}`); lines.push(`- **State:** ${post.lifecycleState}`); if (post.createdAt) { lines.push(`- **Created:** ${new Date(post.createdAt).toISOString()}`); } if (post.commentary) { lines.push("", "**Text:**", post.commentary); } return lines.join("\n"); } - Generic REST GET helper used by the handler to fetch the post from LinkedIn API
export async function restGet<T>(path: string, params?: Record<string, unknown>): Promise<T> { const response = await axios.get<T>(`${LINKEDIN_API_REST_BASE}${path}`, { headers: buildHeaders(true), params, timeout: REQUEST_TIMEOUT_MS, }); return response.data; }