@luffysolution/omnischolar-pi 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +9 -0
- package/README.md +153 -0
- package/README.zh-CN.md +151 -0
- package/package.json +63 -0
- package/pi-extension/dist/index.d.ts +6 -0
- package/pi-extension/dist/index.js +72 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OmniScholar contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# OmniScholar
|
|
2
|
+
|
|
3
|
+
<!-- mcp-name: io.github.luffysolution-svg/omnischolar -->
|
|
4
|
+
|
|
5
|
+
English | [简体中文](README.zh-CN.md)
|
|
6
|
+
|
|
7
|
+
OmniScholar adds literature search, local Zotero reading, PDF parsing, citation tools, materials data, and scientific image generation to coding agents through a local Python MCP server.
|
|
8
|
+
|
|
9
|
+
It can search public indexes, combine online records with your Zotero notes, send an approved PDF to MinerU, and publish Markdown into a regular folder or an Obsidian vault. Zotero access is read-only.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- Search Semantic Scholar, OpenAlex, PubMed/PMC, arXiv, Crossref, Unpaywall, easyScholar, Google Scholar, and Google Patents
|
|
14
|
+
- Retrieve paper details, authors, citations, references, recommendations, snippets, datasets, and journal metrics
|
|
15
|
+
- Read Zotero collections, items, notes, annotations, attachments, indexed text, and local PDF paths without changing the library
|
|
16
|
+
- Parse selected PDFs with MinerU and keep text, formulas, tables, and figures together
|
|
17
|
+
- Find citation candidates, check bibliographic identity, and format accepted references
|
|
18
|
+
- Query Materials Project and export JSON, CSV, Markdown, or CIF
|
|
19
|
+
- Generate or edit scientific illustrations with configured image services
|
|
20
|
+
- Preserve local Markdown edits and place incoming conflict versions in `.conflicts/`
|
|
21
|
+
|
|
22
|
+
OmniScholar exposes 38 tools. See the [tool list](docs/TOOLS.en.md).
|
|
23
|
+
|
|
24
|
+
## Install
|
|
25
|
+
|
|
26
|
+
Python 3.11 or newer is required:
|
|
27
|
+
|
|
28
|
+
```sh
|
|
29
|
+
uv tool install luffysolution-omnischolar
|
|
30
|
+
# or
|
|
31
|
+
pipx install luffysolution-omnischolar
|
|
32
|
+
# or
|
|
33
|
+
python -m pip install luffysolution-omnischolar
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
For development from a source checkout, replace the package name with `.`.
|
|
37
|
+
|
|
38
|
+
The distribution name is `luffysolution-omnischolar`; the command and Python package are `omnischolar`.
|
|
39
|
+
|
|
40
|
+
Check the installation:
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
omnischolar --version
|
|
44
|
+
omnischolar doctor --json
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Connect an agent
|
|
48
|
+
|
|
49
|
+
Preview the files that will change, then install the local MCP entry and Skills:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
omnischolar install --dry-run claude
|
|
53
|
+
omnischolar install claude
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Replace `claude` with `codex`, `cursor`, `opencode`, `hermes`, `pi`, or `workbuddy`. Codex, Claude Code, Cursor, OpenCode, Pi, and WorkBuddy/CodeBuddy support both user and project scopes. Hermes supports user-level MCP configuration; project-level installation adds Skills and reports that MCP setup is manual.
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
omnischolar install cursor --scope project
|
|
60
|
+
omnischolar update cursor --scope project
|
|
61
|
+
omnischolar uninstall cursor --scope project
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
For Pi, the full installer runs `pi install npm:@luffysolution/omnischolar-pi` and installs the bundled Skills separately. The npm Extension starts `omnischolar mcp`, discovers its tools, and registers them with Pi. You can also install the Extension directly:
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
pi install npm:@luffysolution/omnischolar-pi
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
WorkBuddy/CodeBuddy uses `~/.codebuddy/.mcp.json` for user scope and `.mcp.json` for project scope. It does not publish a portable Skills path, so its installer configures MCP and reports Skills as `manual_required`.
|
|
71
|
+
|
|
72
|
+
The MCP command is:
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
omnischolar mcp
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Normally the agent starts this process from its MCP configuration. The installer checks `initialize`, `tools/list`, and `omnischolar_status` after writing a supported configuration.
|
|
79
|
+
|
|
80
|
+
Full host and update instructions are in [Installation](docs/INSTALLATION.en.md).
|
|
81
|
+
|
|
82
|
+
## Try it
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
Find five recent reviews about solid-state battery interfaces. Deduplicate by DOI and show open-access copies.
|
|
86
|
+
|
|
87
|
+
Find this DOI in my Zotero library and summarize my notes and annotations without changing Zotero.
|
|
88
|
+
|
|
89
|
+
After I approve the upload, parse this PDF with MinerU and save a reading note in my Obsidian vault.
|
|
90
|
+
|
|
91
|
+
Query stable Li-Fe-P-O materials in Materials Project and export the selected records as CSV and CIF.
|
|
92
|
+
|
|
93
|
+
Create a labelled illustration of this mechanism. Treat it as a draft, not experimental data.
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Configuration
|
|
97
|
+
|
|
98
|
+
Copy [`omnischolar.config.example.json`](omnischolar.config.example.json) to `omnischolar.config.json`. Keep API keys in environment variables and refer to their names with `apiKeyEnv`.
|
|
99
|
+
|
|
100
|
+
A small local configuration can start with Zotero and the output directory:
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"schemaVersion": 1,
|
|
105
|
+
"runtime": { "workspaceRoots": ["./research-inputs"] },
|
|
106
|
+
"zotero": {
|
|
107
|
+
"enabled": true,
|
|
108
|
+
"baseUrl": "http://127.0.0.1:23119/api"
|
|
109
|
+
},
|
|
110
|
+
"output": { "rootDirectory": "./research-output" }
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
OpenAlex, PubMed, arXiv, and Crossref work without API keys. Other services are enabled separately. Configuration fields and provider examples are in [Configuration](docs/CONFIGURATION.en.md).
|
|
115
|
+
|
|
116
|
+
## Files, uploads, and charges
|
|
117
|
+
|
|
118
|
+
- Zotero requests go only to the local API on port `23119` and use GET.
|
|
119
|
+
- MinerU receives a PDF only when `allowExternalUpload` is enabled in the config and confirmed again in that tool call.
|
|
120
|
+
- Image services receive prompts and any reference images selected for upload. Generation may use account credit.
|
|
121
|
+
- Ai4Scholar calls may use account credit. A stored key does not by itself approve a paid call.
|
|
122
|
+
- A failed paid request is not retried automatically when the provider may already have accepted it.
|
|
123
|
+
- Generated images are illustrations. They are not measurements, experimental evidence, or scientific results.
|
|
124
|
+
|
|
125
|
+
See [`PRIVACY.md`](PRIVACY.md) and [Configuration](docs/CONFIGURATION.en.md) before enabling uploads or paid services.
|
|
126
|
+
|
|
127
|
+
## Included Skills
|
|
128
|
+
|
|
129
|
+
| Skill | Use |
|
|
130
|
+
|---|---|
|
|
131
|
+
| `omnischolar` | Choose and combine tools for a research request |
|
|
132
|
+
| `scholar-search` | Literature, patents, authors, citation graphs, journals, and datasets |
|
|
133
|
+
| `zotero-research` | Local Zotero matching, notes, annotations, and attachments |
|
|
134
|
+
| `paper-reading` | MinerU parsing and close reading of text, formulas, tables, and figures |
|
|
135
|
+
| `academic-citation` | Evidence checks, citation candidates, formatting, and bibliographies |
|
|
136
|
+
| `scientific-figure` | Image generation, editing, review, and scientific labelling |
|
|
137
|
+
| `materials-project` | Materials screening, properties, provenance, phase data, and export |
|
|
138
|
+
| `chemical-data` | CAS Common Chemistry records when an official interface description is configured |
|
|
139
|
+
|
|
140
|
+
## Documentation
|
|
141
|
+
|
|
142
|
+
- [Installation and agent setup](docs/INSTALLATION.en.md)
|
|
143
|
+
- [Configuration and service credentials](docs/CONFIGURATION.en.md)
|
|
144
|
+
- [Literature, Zotero, MinerU, citations, and output](docs/RESEARCH.en.md)
|
|
145
|
+
- [Materials and chemistry](docs/MATERIALS.en.md)
|
|
146
|
+
- [Scientific image providers](docs/IMAGE_PROVIDERS.en.md)
|
|
147
|
+
- [Tool list](docs/TOOLS.en.md)
|
|
148
|
+
|
|
149
|
+
## Support and license
|
|
150
|
+
|
|
151
|
+
OmniScholar is open source under the [MIT License](LICENSE). Open a [GitHub issue](https://github.com/luffysolution-svg/omnischolar/issues) or email `LuffySolution@gmail.com`. Remove keys, signed URLs, private paper content, and personal Zotero data before sending a report.
|
|
152
|
+
|
|
153
|
+
Third-party services and datasets keep their own terms and licenses. See [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md).
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# OmniScholar
|
|
2
|
+
|
|
3
|
+
[English](README.md) | 简体中文
|
|
4
|
+
|
|
5
|
+
OmniScholar 通过本地 Python MCP 服务,为 Codex、Claude Code、Cursor、OpenCode、Hermes 和 Pi 等 Agent 提供文献检索、Zotero 读取、PDF 解析、引用处理、材料数据和科研绘图工具。
|
|
6
|
+
|
|
7
|
+
它可以把在线文献记录与 Zotero 笔记放在一起处理,将经你确认的 PDF 交给 MinerU 解析,再把 Markdown 保存到普通文件夹或 Obsidian Vault。Zotero 全程只读。
|
|
8
|
+
|
|
9
|
+
## 功能
|
|
10
|
+
|
|
11
|
+
- 检索 Semantic Scholar、OpenAlex、PubMed/PMC、arXiv、Crossref、Unpaywall、easyScholar、Google Scholar 和 Google Patents
|
|
12
|
+
- 查询论文详情、作者、参考文献、施引文献、推荐、全文片段、数据集和期刊指标
|
|
13
|
+
- 读取 Zotero 收藏夹、条目、笔记、批注、附件、索引文本和本地 PDF 路径,不修改文献库
|
|
14
|
+
- 使用 MinerU 提取指定 PDF 的正文、公式、表格和图片
|
|
15
|
+
- 查找引用候选,核对书目信息,再按要求生成参考文献
|
|
16
|
+
- 查询 Materials Project,并导出 JSON、CSV、Markdown 或 CIF
|
|
17
|
+
- 调用已配置的图片服务生成或编辑科研示意图
|
|
18
|
+
- 保留手工修改过的 Markdown,把待合并版本放入 `.conflicts/`
|
|
19
|
+
|
|
20
|
+
OmniScholar 共提供 38 个工具,完整列表见[工具目录](docs/TOOLS.md)。
|
|
21
|
+
|
|
22
|
+
## 安装
|
|
23
|
+
|
|
24
|
+
需要 Python 3.11 或更高版本:
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
uv tool install luffysolution-omnischolar
|
|
28
|
+
# 或
|
|
29
|
+
pipx install luffysolution-omnischolar
|
|
30
|
+
# 或
|
|
31
|
+
python -m pip install luffysolution-omnischolar
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
如需从源码开发安装,请将包名替换为 `.`。
|
|
35
|
+
|
|
36
|
+
发行包名为 `luffysolution-omnischolar`,命令和 Python 包名都是 `omnischolar`。
|
|
37
|
+
|
|
38
|
+
检查安装结果:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
omnischolar --version
|
|
42
|
+
omnischolar doctor --json
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 连接 Agent
|
|
46
|
+
|
|
47
|
+
先查看将要修改的文件,再安装本地 MCP 配置和 Skills:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
omnischolar install --dry-run claude
|
|
51
|
+
omnischolar install claude
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
可将 `claude` 换成 `codex`、`cursor`、`opencode`、`hermes`、`pi` 或 `workbuddy`。Codex、Claude Code、Cursor、OpenCode、Pi 和 WorkBuddy/CodeBuddy 支持用户级与项目级安装。Hermes 只提供用户级 MCP 配置;项目级命令会安装 Skills,并提示 MCP 需要手动设置。
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
omnischolar install cursor --scope project
|
|
58
|
+
omnischolar update cursor --scope project
|
|
59
|
+
omnischolar uninstall cursor --scope project
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
对 Pi,完整安装器会运行 `pi install npm:@luffysolution/omnischolar-pi`,并单独安装随包提供的 Skills。npm Extension 会启动 `omnischolar mcp`、发现工具并注册到 Pi。也可以直接安装 Extension:
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
pi install npm:@luffysolution/omnischolar-pi
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
WorkBuddy/CodeBuddy 的用户级配置位于 `~/.codebuddy/.mcp.json`,项目级配置位于 `.mcp.json`。其官方文档没有给出可移植的 Skills 目录,因此安装器会配置 MCP,并将 Skills 状态报告为 `manual_required`。
|
|
69
|
+
|
|
70
|
+
本地 MCP 命令为:
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
omnischolar mcp
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
通常无需手动运行,Agent 会根据 MCP 配置启动该进程。安装器写入受支持的配置后,会检查 `initialize`、`tools/list` 和 `omnischolar_status`。
|
|
77
|
+
|
|
78
|
+
各 Agent 的路径、更新和卸载方法见[安装说明](docs/INSTALLATION.md)。
|
|
79
|
+
|
|
80
|
+
## 使用示例
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
查找 5 篇关于固态电池界面的近期综述,按 DOI 去重,并给出开放获取版本。
|
|
84
|
+
|
|
85
|
+
在我的 Zotero 中找到这个 DOI,汇总笔记和批注,不要修改 Zotero。
|
|
86
|
+
|
|
87
|
+
我确认上传后,用 MinerU 解析这份 PDF,并把阅读笔记保存到 Obsidian Vault。
|
|
88
|
+
|
|
89
|
+
查询 Materials Project 中稳定的 Li-Fe-P-O 材料,将选中的记录导出为 CSV 和 CIF。
|
|
90
|
+
|
|
91
|
+
为这个机理绘制带标签的示意图。图片只是草稿,不得写成实验数据。
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## 配置
|
|
95
|
+
|
|
96
|
+
将 [`omnischolar.config.example.json`](omnischolar.config.example.json) 复制为 `omnischolar.config.json`。API key 建议放在环境变量中,配置文件只填写变量名 `apiKeyEnv`。
|
|
97
|
+
|
|
98
|
+
最小的本地配置可以只写 Zotero 和输出目录:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"schemaVersion": 1,
|
|
103
|
+
"runtime": { "workspaceRoots": ["./research-inputs"] },
|
|
104
|
+
"zotero": {
|
|
105
|
+
"enabled": true,
|
|
106
|
+
"baseUrl": "http://127.0.0.1:23119/api"
|
|
107
|
+
},
|
|
108
|
+
"output": { "rootDirectory": "./research-output" }
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
OpenAlex、PubMed、arXiv 和 Crossref 无需 API key。其他服务按需启用,字段和示例见[配置说明](docs/CONFIGURATION.md)。
|
|
113
|
+
|
|
114
|
+
## 文件、上传与费用
|
|
115
|
+
|
|
116
|
+
- Zotero 只连接本机 `23119` 端口,并且只发送 GET 请求。
|
|
117
|
+
- MinerU 只有在配置和本次工具调用都确认 `allowExternalUpload` 后,才会接收选中的 PDF。
|
|
118
|
+
- 图片服务会接收提示词,以及你允许上传的参考图;生成和编辑可能消耗账户额度。
|
|
119
|
+
- Ai4Scholar 的部分调用可能消耗账户额度。仅保存 API key 不代表同意付费调用。
|
|
120
|
+
- 付费请求发生网络错误后,如果无法确定服务端是否已经受理,OmniScholar 不会自动重试。
|
|
121
|
+
- AI 生成图只能作为示意图,不能当作测量数据、实验证据或科研结果。
|
|
122
|
+
|
|
123
|
+
启用上传或付费服务前,请阅读 [`PRIVACY.md`](PRIVACY.md) 和[配置说明](docs/CONFIGURATION.md)。
|
|
124
|
+
|
|
125
|
+
## 内置 Skills
|
|
126
|
+
|
|
127
|
+
| Skill | 用途 |
|
|
128
|
+
|---|---|
|
|
129
|
+
| `omnischolar` | 根据科研任务选择并组合工具 |
|
|
130
|
+
| `scholar-search` | 文献、专利、作者、引用网络、期刊和数据集 |
|
|
131
|
+
| `zotero-research` | 本地 Zotero 匹配、笔记、批注和附件 |
|
|
132
|
+
| `paper-reading` | MinerU 解析,以及正文、公式、表格和图片精读 |
|
|
133
|
+
| `academic-citation` | 证据核对、引用候选、格式化和参考文献 |
|
|
134
|
+
| `scientific-figure` | 科研图片生成、编辑、检查和标注 |
|
|
135
|
+
| `materials-project` | 材料筛选、性质、计算来源、相数据和导出 |
|
|
136
|
+
| `chemical-data` | 配置正式 API 说明后查询 CAS Common Chemistry |
|
|
137
|
+
|
|
138
|
+
## 文档
|
|
139
|
+
|
|
140
|
+
- [安装与 Agent 配置](docs/INSTALLATION.md)
|
|
141
|
+
- [配置与服务凭据](docs/CONFIGURATION.md)
|
|
142
|
+
- [文献、Zotero、MinerU、引用与输出](docs/RESEARCH.md)
|
|
143
|
+
- [材料与化学](docs/MATERIALS.md)
|
|
144
|
+
- [科研绘图服务](docs/IMAGE_PROVIDERS.md)
|
|
145
|
+
- [工具目录](docs/TOOLS.md)
|
|
146
|
+
|
|
147
|
+
## 支持与许可证
|
|
148
|
+
|
|
149
|
+
OmniScholar 使用 [MIT License](LICENSE) 开源。可在 [GitHub Issues](https://github.com/luffysolution-svg/omnischolar/issues) 提交问题,或发送邮件到 `LuffySolution@gmail.com`。报告问题前,请删除 API key、签名 URL、私人论文内容和个人 Zotero 数据。
|
|
150
|
+
|
|
151
|
+
第三方服务和数据仍遵循各自的条款与许可证,详见 [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md)。
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@luffysolution/omnischolar-pi",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Pi MCP bridge for the OmniScholar research toolkit",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "OmniScholar contributors <LuffySolution@gmail.com>",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/luffysolution-svg/omnischolar.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/luffysolution-svg/omnischolar#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/luffysolution-svg/omnischolar/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"pi-package",
|
|
18
|
+
"pi-extension",
|
|
19
|
+
"mcp",
|
|
20
|
+
"research",
|
|
21
|
+
"literature",
|
|
22
|
+
"zotero"
|
|
23
|
+
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=22.19.0"
|
|
26
|
+
},
|
|
27
|
+
"exports": "./pi-extension/dist/index.js",
|
|
28
|
+
"types": "./pi-extension/dist/index.d.ts",
|
|
29
|
+
"files": [
|
|
30
|
+
"pi-extension/dist",
|
|
31
|
+
"README.md",
|
|
32
|
+
"LICENSE"
|
|
33
|
+
],
|
|
34
|
+
"pi": {
|
|
35
|
+
"extensions": [
|
|
36
|
+
"./pi-extension/dist/index.js"
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsc -p pi-extension/tsconfig.json",
|
|
41
|
+
"check": "tsc -p pi-extension/tsconfig.json --noEmit",
|
|
42
|
+
"test": "tsx --test pi-extension/test/*.test.ts",
|
|
43
|
+
"prepack": "npm run build",
|
|
44
|
+
"prepublishOnly": "npm test && npm run check"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@modelcontextprotocol/sdk": "^1.30.0"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
51
|
+
"typebox": "*"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@earendil-works/pi-coding-agent": "^0.85.1",
|
|
55
|
+
"@types/node": "^24.0.0",
|
|
56
|
+
"tsx": "^4.21.0",
|
|
57
|
+
"typebox": "^1.3.30",
|
|
58
|
+
"typescript": "^5.9.3"
|
|
59
|
+
},
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
3
|
+
import type { CallToolResult, Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
+
export declare function resultText(result: CallToolResult): string;
|
|
5
|
+
export declare function registerMcpTool(pi: ExtensionAPI, client: Client, tool: Tool): void;
|
|
6
|
+
export default function omnischolarExtension(pi: ExtensionAPI): void;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
3
|
+
import { Type } from "typebox";
|
|
4
|
+
const CLIENT_INFO = { name: "omnischolar-pi", version: "0.1.0" };
|
|
5
|
+
export function resultText(result) {
|
|
6
|
+
return result.content
|
|
7
|
+
.map((item) => {
|
|
8
|
+
if (item.type === "text")
|
|
9
|
+
return item.text;
|
|
10
|
+
return JSON.stringify(item);
|
|
11
|
+
})
|
|
12
|
+
.join("\n");
|
|
13
|
+
}
|
|
14
|
+
export function registerMcpTool(pi, client, tool) {
|
|
15
|
+
pi.registerTool({
|
|
16
|
+
name: tool.name,
|
|
17
|
+
label: tool.title ?? tool.name.replaceAll("_", " "),
|
|
18
|
+
description: tool.description ?? `Call the OmniScholar ${tool.name} tool.`,
|
|
19
|
+
parameters: Type.Unsafe(tool.inputSchema),
|
|
20
|
+
async execute(_toolCallId, params, signal) {
|
|
21
|
+
const result = (await client.callTool({ name: tool.name, arguments: params }, undefined, { signal }));
|
|
22
|
+
const text = resultText(result);
|
|
23
|
+
if (result.isError)
|
|
24
|
+
throw new Error(text || `${tool.name} failed`);
|
|
25
|
+
return {
|
|
26
|
+
content: [{ type: "text", text }],
|
|
27
|
+
details: result.structuredContent ?? {},
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
export default function omnischolarExtension(pi) {
|
|
33
|
+
let client;
|
|
34
|
+
let transport;
|
|
35
|
+
let connection;
|
|
36
|
+
const connect = () => {
|
|
37
|
+
if (connection)
|
|
38
|
+
return connection;
|
|
39
|
+
connection = (async () => {
|
|
40
|
+
transport = new StdioClientTransport({
|
|
41
|
+
command: "omnischolar",
|
|
42
|
+
args: ["mcp"],
|
|
43
|
+
stderr: "pipe",
|
|
44
|
+
});
|
|
45
|
+
client = new Client(CLIENT_INFO);
|
|
46
|
+
await client.connect(transport);
|
|
47
|
+
const { tools } = await client.listTools();
|
|
48
|
+
for (const tool of tools)
|
|
49
|
+
registerMcpTool(pi, client, tool);
|
|
50
|
+
})();
|
|
51
|
+
return connection;
|
|
52
|
+
};
|
|
53
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
54
|
+
try {
|
|
55
|
+
await connect();
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
connection = undefined;
|
|
59
|
+
await client?.close().catch(() => undefined);
|
|
60
|
+
client = undefined;
|
|
61
|
+
transport = undefined;
|
|
62
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
63
|
+
ctx.ui.notify(`OmniScholar MCP did not start: ${message}`, "error");
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
pi.on("session_shutdown", async () => {
|
|
67
|
+
await client?.close().catch(() => undefined);
|
|
68
|
+
client = undefined;
|
|
69
|
+
transport = undefined;
|
|
70
|
+
connection = undefined;
|
|
71
|
+
});
|
|
72
|
+
}
|