From 7047a4ebacc7e56692ac577ee21800a5ee622a5d Mon Sep 17 00:00:00 2001 From: locip123 <116343912+locip123@users.noreply.github.com> Date: Wed, 23 Sep 2026 15:43:59 +0800 Subject: [PATCH] feat(connectors): add OpenAlex connector (#1009) * feat(connectors): add OpenAlex connector * feat(connectors): add OpenAlex connector --- dashboard/src/assets/connectors/index.ts | 2 + dashboard/src/assets/connectors/openalex.svg | 145 ++++++++++++++++++ .../Agent/Connectors/ConnectorCard.test.tsx | 17 ++ src/octop/infra/connectors/catalog.py | 19 +++ tests/integration/test_connectors_api.py | 23 +++ 5 files changed, 206 insertions(+) create mode 100644 dashboard/src/assets/connectors/openalex.svg diff --git a/dashboard/src/assets/connectors/index.ts b/dashboard/src/assets/connectors/index.ts index 1ea8f26e..3ce373e2 100644 --- a/dashboard/src/assets/connectors/index.ts +++ b/dashboard/src/assets/connectors/index.ts @@ -8,6 +8,7 @@ import feishuCli from "./feishu-cli.png"; import fliggy from "./fliggy.png"; import meituanTravel from "./meituan-travel.png"; import notion from "./notion.png"; +import openalex from "./openalex.svg"; import qqMail from "./qq-mail.png"; import qqMusic from "./qq-music.png"; import tencentDocs from "./tencent-docs.png"; @@ -39,6 +40,7 @@ export const CONNECTOR_LOGOS: Record = { "tencent-lexiang": tencentLexiang, "tencent-meeting": tencentMeeting, notion, + openalex, dida365: dida365, dify, "tencent-news": tencentNews, diff --git a/dashboard/src/assets/connectors/openalex.svg b/dashboard/src/assets/connectors/openalex.svg new file mode 100644 index 00000000..bc0deff2 --- /dev/null +++ b/dashboard/src/assets/connectors/openalex.svg @@ -0,0 +1,145 @@ + + + + + + diff --git a/dashboard/src/pages/Agent/Connectors/ConnectorCard.test.tsx b/dashboard/src/pages/Agent/Connectors/ConnectorCard.test.tsx index 376502dc..7bfbd18e 100644 --- a/dashboard/src/pages/Agent/Connectors/ConnectorCard.test.tsx +++ b/dashboard/src/pages/Agent/Connectors/ConnectorCard.test.tsx @@ -41,4 +41,21 @@ describe("", () => { const title = screen.getByText(LONG_NAME); expect(title.className).toContain("typography-ellipsis"); }); + + it("renders the OpenAlex catalog logo instead of the generic MCP fallback", () => { + const { container } = render( + undefined} + />, + ); + + expect(container.querySelector("img")?.getAttribute("src")).toContain( + "openalex.svg", + ); + }); }); diff --git a/src/octop/infra/connectors/catalog.py b/src/octop/infra/connectors/catalog.py index 10437e3b..d1c49519 100644 --- a/src/octop/infra/connectors/catalog.py +++ b/src/octop/infra/connectors/catalog.py @@ -410,6 +410,25 @@ _CATALOG: tuple[ConnectorCatalogEntry, ...] = ( mcp_url="https://mcp.notion.com/mcp", mcp_user_agent="octop-connector/0.1", ), + ConnectorCatalogEntry( + kind="openalex", + name="OpenAlex", + description="官方 MCP:检索学术文献、引文、研究实体与统计分析", + auth_kind="oauth2", + doc_url="https://help.openalex.org/access/connector/", + icon="openalex", + color="#1f6feb", + phase="available", + mcp_mode="remote", + category="knowledge", + guide_url="https://help.openalex.org/access/connector/", + auth_hint="点击「一键授权」登录 OpenAlex;查询将使用你自己的 API Key 与每日预算。", + oauth_issuer="https://mcp.openalex.org", + mcp_url="https://mcp.openalex.org/mcp", + oauth_resource="https://mcp.openalex.org/mcp", + oauth_scopes="openalex:query", + remote_transport="streamable_http", + ), ConnectorCatalogEntry( kind="dida365", name="滴答清单", diff --git a/tests/integration/test_connectors_api.py b/tests/integration/test_connectors_api.py index b039ab7f..5bd5012f 100644 --- a/tests/integration/test_connectors_api.py +++ b/tests/integration/test_connectors_api.py @@ -34,6 +34,7 @@ async def test_catalog(env): assert "figma" not in kinds assert "baidu-netdisk" not in kinds for kind in ( + "openalex", "tencent-meeting", "tencent-lexiang", "notion", @@ -63,6 +64,28 @@ async def test_catalog(env): assert weiyun["mcp_mode"] == "remote" assert weiyun["category"] == "office" assert weiyun.get("quick_auth_url") == "https://www.weiyun.com/act/openclaw" + openalex = next(e for e in r.json() if e["kind"] == "openalex") + assert openalex == { + "kind": "openalex", + "name": "OpenAlex", + "description": "官方 MCP:检索学术文献、引文、研究实体与统计分析", + "auth_kind": "oauth2", + "doc_url": "https://help.openalex.org/access/connector/", + "icon": "openalex", + "color": "#1f6feb", + "phase": "available", + "mcp_mode": "remote", + "category": "knowledge", + "quick_auth_url": None, + "login_url": None, + "guide_url": "https://help.openalex.org/access/connector/", + "manual_url": "https://help.openalex.org/access/connector/", + "auth_hint": "点击「一键授权」登录 OpenAlex;查询将使用你自己的 API Key 与每日预算。", + "oauth_mode": "dynamic", + "oauth_ready": True, + "credential_fields": [], + "supports_quick_auth": True, + } async def test_create_tencent_instance(env):