LinkedIn MCP服务

LinkedIn MCP服务是一个为AI代理提供结构化工具接口的服务器,支持LinkedIn相关操作如个人资料查询、内容发布和图像上传等功能。

  • by hashan-silva
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 hashan-silva/linkedin-mcp-server

使用说明

LinkedIn MCP服务器

如果你在人工智能代理周围花了足够的时间,你会一遍又一遍地听到同样的承诺:代理不仅会回答问题,还会工作。

如果模型不能安全可靠地与真实系统交互,那么这一承诺只有一部分是正确的。

一个不会使用工具的代理人通常是一个很好的健谈者。一个能够发现工具、理解其输入并执行实际操作的代理开始变得有用。

这就是MCP发挥作用的地方。

这个项目是一个LinkedIn MCP服务器,通过一个干净的工具界面公开LinkedIn的功能。服务器没有要求模型猜测如何调用LinkedIn API,而是为模型提供了一组结构化的操作,用于个人资料查找、内容发布、图像发布和文章共享。

GitHub存储库: https://github.com/hashan-silva/linkedin-mcp-server
Docker镜像: hashan0314/linkedin-mcp-server

您需要一个具有适当范围的有效LinkedIn OAuth访问令牌。令牌不存储在此项目中;通过环境变量提供它们或使用内置的OAuth流。

什么是MCP

MCP代表模型上下文协议。

最简单的思考方式是:MCP为AI代理提供了一种使用工具的标准方法。

如果没有MCP,开发人员通常会在提示中描述API,并希望模型完全遵循这些说明。这种方法是脆弱的。模型可以发明参数,跳过所需的字段,或者滥用他们只能部分理解的API形状。

MCP用结构取代了这种猜测。

MCP服务器告诉代理:

  • 存在哪些工具
  • 每个工具的作用
  • 需要哪些输入
  • 结果如何返回

在这个项目中,服务器从标准输入读取JSON消息,并将JSON响应写入标准输出。传输故意轻量级,但接口明确可靠。

while True:
    line = await reader.readline()
    if not line:
        break

    message = json.loads(line.decode())
    response = await self.handle_message(message)

    if response is not None:
        writer.write((json.dumps(response) + "\n").encode())
        await writer.drain()

这就是MCP服务器的基本形状:接收结构化请求,路由它,返回结构化响应。

为什么MCP对Agent AI很重要

MCP的真正价值不在于它允许代理访问。它为他们提供了有纪律的访问权限。

这很重要,因为特工需要的不仅仅是情报。它需要可靠的方式与外部系统进行交互。MCP在几个重要方面对此有所帮助。

它使工具的使用变得明确

与其希望模型记住LinkedIn帖子的工作原理,不如公开一个类似的工具 create_text_post 或 create_article_post.

此项目中的一个工具定义如下:

{
    "name": "create_article_post",
    "description": "Create a LinkedIn article post with an external article link.",
    "inputSchema": {
        "type": "object",
        "properties": {
            "author": {"type": "string"},
            "commentary": {"type": "string"},
            "articleSource": {"type": "string"},
            "articleTitle": {"type": "string"},
            "articleDescription": {"type": "string"},
        },
        "required": [
            "author",
            "commentary",
            "articleSource",
            "articleTitle",
            "articleDescription",
        ],
    },
}

这比在提示中隐藏API指令要可靠得多。

它将推理与执行分开

模型决定它想做什么。服务器处理它是如何完成的。

这意味着代理可以专注于以下决策:

  • 我应该先获取个人资料吗?
  • 我应该创建文本帖子还是文章帖子?
  • 在发布媒体之前,我需要初始化图像上传吗?

然后,服务器会处理其余的事情:

  • 标头和身份验证
  • LinkedIn API端点
  • 有效载荷结构
  • 上传流
  • 错误处理

它使代理人更容易管理

一个聚焦的MCP服务器只公开您希望代理执行的操作。

这比给模型广泛的网络自由并希望它正确运行更安全。在这个项目中,模型只能使用服务器显式公开的LinkedIn操作。

它使集成可重用

一旦将功能包装为MCP,多个代理就可以使用它。同一台服务器可以插入Codex CLI、本地工作流或容器化环境。

这时,集成不再是一种快速的技巧,而是开始成为基础设施。

此服务器的功能

从高层次上讲,LinkedIn MCP服务器做了三件事:

  • 将LinkedIn相关工具暴露给AI代理
  • 将工具调用转换为LinkedIn REST API请求
  • 通过访问令牌或内置OAuth流处理身份验证

该架构有意保持简洁。一层公开工具,一层与LinkedIn对话,一个助手处理OAuth。

外露工具

  • get_profile
  • get_verification_report
  • get_userinfo
  • create_text_post
  • create_reshare
  • initialize_image_upload
  • upload_image_binary
  • create_image_post
  • create_multi_image_post
  • create_article_post

服务器将工具调用直接发送到LinkedIn客户端:

if name == "get_profile":
    return self.client.get_profile()

if name == "create_text_post":
    return self.client.create_post(
        author=args.get("author", ""),
        commentary=args.get("commentary", ""),
        visibility=args.get("visibility", "PUBLIC"),
    )

if name == "create_article_post":
    return self.client.create_article_post(
        author=args.get("author", ""),
        commentary=args.get("commentary", ""),
        article_source=args.get("articleSource", ""),
        article_title=args.get("articleTitle", ""),
        article_description=args.get("articleDescription", ""),
    )

这种直接性是该项目的优势之一。MCP不必复杂才能有用。

LinkedIn功能

此服务器支持有意义的LinkedIn工作流,而不仅仅是展示玩具演示。

配置文件和身份查找

服务器可以检索:

  • 当前成员配置文件
  • 验证报告
  • OpenID连接用户信息

个人资料查找是对LinkedIn身份端点的直接调用:

resp = self.session.get(
    self._url("/rest/identityMe"),
    headers={"LinkedIn-Version": "202510.03"},
)

这会在代理开始代表用户行事之前提供代理上下文。

文本帖子创建

这 create_text_post 该工具允许代理发布标准的纯文本LinkedIn帖子。

有效载荷包括作者、评论、可见性、分发设置和生命周期状态:

return {
    "author": author_value,
    "commentary": commentary_value,
    "visibility": visibility,
    "distribution": distribution or {
        "feedDistribution": "MAIN_FEED",
        "targetEntities": [],
        "thirdPartyDistributionChannels": [],
    },
    "lifecycleState": lifecycle_state,
    "isReshareDisabledByAuthor": is_reshare_disabled_by_author,
}

代理不需要知道LinkedIn的有效载荷形状。它只是以正确的意图和论据调用工具。

重新共享

这 create_reshare 该工具允许代理人重新发布现有的领英帖子,并添加可选的评论。

有效载荷包括 reshareContext 这指向了父帖子:

payload = {
    "author": author_value,
    "visibility": visibility,
    "distribution": distribution or {
        "feedDistribution": "MAIN_FEED",
        "targetEntities": [],
        "thirdPartyDistributionChannels": [],
    },
    "lifecycleState": lifecycle_state,
    "isReshareDisabledByAuthor": is_reshare_disabled_by_author,
    "reshareContext": {"parent": parent_value},
}

图片上传和图片发布

媒体发布被有意建模为一个多步骤的工作流程:

  1. 初始化上传
  2. 接收上传URL和图像URN
  3. 上传图像二进制文件
  4. 创建引用上传媒体的最终帖子

上传初始化步骤如下:

resp = self.session.post(
    self._url("/rest/images?action=initializeUpload"),
    json={"initializeUploadRequest": {"owner": owner_value}},
    headers={"LinkedIn-Version": linkedin_version},
)

然后,二进制上传直接发送到提供的上传URL:

with path.open("rb") as handle:
    resp = requests.put(
        url_value,
        data=handle,
        headers={"Content-Type": "application/octet-stream"},
    )

这反映了真实的LinkedIn流程,而不是将其隐藏在不切实际的一步抽象之后。

多图像帖子

这 create_multi_image_post 该工具允许代理通过构建一个 multiImage 内容结构:

return {
    "author": author_value,
    "commentary": commentary_value,
    "visibility": visibility,
    "distribution": distribution or {
        "feedDistribution": "MAIN_FEED",
        "targetEntities": [],
        "thirdPartyDistributionChannels": [],
    },
    "lifecycleState": lifecycle_state,
    "isReshareDisabledByAuthor": is_reshare_disabled_by_author,
    "content": {"multiImage": {"images": image_items}},
}

文章帖子

这 create_article_post 该工具对于较长的表单内容工作流特别有用。它允许代理发布链接到外部文章的LinkedIn帖子,如Medium帖子。

return {
    "author": author_value,
    "commentary": commentary_value,
    "visibility": visibility,
    "lifecycleState": lifecycle_state,
    "content": {
        "article": {
            "source": source_value,
            "title": title_value,
            "description": description_value,
        }
    },
    "distribution": distribution or {"feedDistribution": "MAIN_FEED"},
}

这是MCP将混乱的外部API功能转变为代理可以使用的干净工具的一个有力例子。

认证

身份验证是许多演示变得不切实际的地方。这个项目以一种实用的方式处理它。

您可以:

  • 提供 LINKEDIN_ACCESS_TOKEN 直接
  • 使用以下命令启动服务器 --auth 并完成OAuth流程

授权URL的构建方式如下:

params = {
    "response_type": "code",
    "client_id": client_id,
    "redirect_uri": redirect_uri,
    "scope": scope,
    "state": state,
}

然后,服务器等待重定向,捕获授权码,并将其交换为访问令牌。内置的OAuth助手使该项目在实践中更容易使用。

特性

  • 获取个人资料
  • 获取验证报告
  • 获取用户信息
  • 创建纯文本帖子
  • 创建转发帖子
  • 创建图片帖子
  • 创建多图像帖子
  • 创建文章帖子

在本地运行

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
export LINKEDIN_ACCESS_TOKEN="<your-token>"
# optional: override API base
# export LINKEDIN_BASE_URL="https://api.linkedin.com"
python -m src.mcp_server

服务器与stdio保持连接,可以在兼容的客户端中配置为MCP服务器。

内置OAuth助手

如果您有LinkedIn应用程序客户端ID和密码,则可以使用OAuth辅助身份验证启动服务器:

export LINKEDIN_CLIENT_ID="your-client-id"
export LINKEDIN_CLIENT_SECRET="your-client-secret"
export LINKEDIN_REDIRECT_URI="http://127.0.0.1:8765/callback"
# optional: scopes
# export LINKEDIN_SCOPE="r_liteprofile w_member_social"
python -m src.mcp_server --auth

服务器打印一个授权URL,等待重定向,用代码交换访问令牌,然后启动MCP循环。

码头工人

构建并运行:

docker build -t linkedin-mcp-server .
docker run --rm -e LINKEDIN_ACCESS_TOKEN="$LINKEDIN_ACCESS_TOKEN" linkedin-mcp-server

使用备用基URL运行:

docker run --rm -e LINKEDIN_ACCESS_TOKEN=... -e LINKEDIN_BASE_URL=https://api.linkedin.com linkedin-mcp-server

直接使用已发布的图像:

docker run --rm -i -e LINKEDIN_ACCESS_TOKEN=... hashan0314/linkedin-mcp-server

不要在图像中添加秘密。在运行时使用环境变量传递凭据,或 --env-file.

Docker中的OAuth:

docker run --rm \
  -p 8765:8765 \
  -e LINKEDIN_CLIENT_ID=... \
  -e LINKEDIN_CLIENT_SECRET=... \
  -e LINKEDIN_REDIRECT_URI=http://127.0.0.1:8765/callback \
  hashan0314/linkedin-mcp-server python -m src.mcp_server --auth

Codex CLI示例

将stdio MCP服务器条目添加到 ~/.codex/config.toml:

[mcp_servers.linkedin]
command = "docker"
args = ["run", "--rm", "-i", "-e", "LINKEDIN_ACCESS_TOKEN", "hashan0314/linkedin-mcp-server"]
env = {"LINKEDIN_ACCESS_TOKEN"="<your_token>"}
startup_timeout_ms = 30000

备注

  • 有意尽量减少验证;LinkedIn API错误会返回给调用方。
  • 请注意LinkedIn的费率限制和代币范围。
  • 如果您看到401或403,则您的令牌可能已过期或缺少所需的作用域。
  • 除了LinkedIn API本身之外,没有实现任何持久性。

为什么这个项目有用

这个项目足够小,可以快速理解,但足够真实,可以证明MCP的重要性。

它显示:

  • 一种真正的stdio MCP传输
  • 明确的工具定义
  • 结构化工具输入
  • 协议和API执行之间的清晰分离
  • 一个实用的身份验证故事
  • 代理可以实际使用的读写工作流

如果你想了解为什么MCP对代理AI很重要,这是核心思想:给模型结构化的工具,把执行逻辑放在提示之外,让代理通过稳定的接口工作,而不是即兴创作。