create-academic-research 0.1.5 → 0.1.7
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/README.md +56 -10
- package/dist/src/capabilities.js +62 -4
- package/dist/src/cli.js +162 -16
- package/dist/src/project.js +10 -2
- package/dist/src/prompts.js +2 -1
- package/dist/src/stack.d.ts +8 -0
- package/dist/src/stack.js +127 -73
- package/package.json +1 -1
- package/template/AGENTS.md +5 -1
- package/template/README.md +22 -7
- package/template/package.json +4 -1
- package/template/scripts/README.md +10 -0
- package/template/tests/test_project_structure.py +7 -0
- package/template/wiki/index.md +9 -0
- package/template/wiki/templates/claim-page.md +24 -0
- package/template/wiki/templates/decision-record.md +26 -0
- package/template/wiki/templates/experiment-page.md +30 -0
- package/template/wiki/templates/research-question.md +27 -0
- package/template/wiki/templates/reviewer-concern.md +25 -0
- package/template/wiki/templates/source-page.md +31 -0
- package/template/wiki/templates/.gitkeep +0 -0
package/README.md
CHANGED
|
@@ -46,11 +46,16 @@ By default, the wizard:
|
|
|
46
46
|
|
|
47
47
|
- creates the repository structure;
|
|
48
48
|
- installs the project-local `VincenzoImp/academic-research-skills` package;
|
|
49
|
-
- enables the
|
|
50
|
-
|
|
49
|
+
- enables only the low-friction `arxiv` MCP record;
|
|
50
|
+
- documents the wider MCP catalog, including Semantic Scholar, OpenAlex, DBLP,
|
|
51
|
+
PubMed, Zotero, Crossref, Overleaf, and fallback aggregators;
|
|
51
52
|
- writes `configs/capabilities.yaml`;
|
|
52
53
|
- writes `docs/agent/capability-profile.md`;
|
|
54
|
+
- writes `docs/agent/mcp-setup.md`;
|
|
53
55
|
- writes `docs/agent/generated/mcp.json` unless an explicit agent target is set;
|
|
56
|
+
- includes `scripts/README.md` for repeatable command entrypoints;
|
|
57
|
+
- includes reusable `wiki/templates/` pages for sources, claims, experiments,
|
|
58
|
+
decisions, reviewer concerns, and research questions;
|
|
54
59
|
- appends the onboarding event to `wiki/log.md`;
|
|
55
60
|
- does not install external MCP tools unless explicitly requested.
|
|
56
61
|
|
|
@@ -58,6 +63,12 @@ Use `--preset enhanced` when you also want the curated complementary external
|
|
|
58
63
|
skill bundles for agent engineering, frontend work, testing, document formats,
|
|
59
64
|
and PDF conversion.
|
|
60
65
|
|
|
66
|
+
Research-specific skills are intentionally not pulled from external packages by
|
|
67
|
+
default. The academic research workflow, literature review, citation audit,
|
|
68
|
+
paper writing, peer review, rebuttal, and reproduction policies come from
|
|
69
|
+
`VincenzoImp/academic-research-skills`. External skills installed by the wizard
|
|
70
|
+
are complementary tooling only.
|
|
71
|
+
|
|
61
72
|
## Non-Interactive Create
|
|
62
73
|
|
|
63
74
|
```bash
|
|
@@ -76,6 +87,7 @@ Inside a generated project:
|
|
|
76
87
|
|
|
77
88
|
```bash
|
|
78
89
|
npx academic-research doctor
|
|
90
|
+
npx academic-research setup
|
|
79
91
|
npx academic-research rename --title "New Title" --slug new-title --package new_title
|
|
80
92
|
npx academic-research agents list
|
|
81
93
|
npx academic-research skills presets
|
|
@@ -90,15 +102,21 @@ npx academic-research mcp list
|
|
|
90
102
|
npx academic-research mcp enabled
|
|
91
103
|
npx academic-research mcp available
|
|
92
104
|
npx academic-research mcp commands arxiv
|
|
93
|
-
npx academic-research mcp
|
|
105
|
+
npx academic-research mcp env openalex semantic-scholar zotero
|
|
106
|
+
npx academic-research mcp enable arxiv dblp
|
|
94
107
|
npx academic-research mcp disable arxiv
|
|
95
108
|
npx academic-research mcp install arxiv
|
|
96
109
|
npx academic-research mcp uninstall arxiv
|
|
110
|
+
npx academic-research mcp smoke
|
|
97
111
|
npx academic-research mcp doctor
|
|
98
112
|
```
|
|
99
113
|
|
|
100
114
|
## Command Model
|
|
101
115
|
|
|
116
|
+
`academic-research setup` is a non-destructive onboarding status command. It
|
|
117
|
+
prints the active preset, agent, skill counts, enabled MCP records, and next
|
|
118
|
+
commands without changing files.
|
|
119
|
+
|
|
102
120
|
Skills are project-local by default.
|
|
103
121
|
|
|
104
122
|
| Command | Meaning |
|
|
@@ -118,11 +136,13 @@ MCP commands are split by side-effect:
|
|
|
118
136
|
| `mcp enabled` | List only enabled MCP server ids. |
|
|
119
137
|
| `mcp available` | List the local MCP catalog. |
|
|
120
138
|
| `mcp commands` | Print finite external install commands without running them. Runtime-only `uvx`/`npx` servers may have no install command. |
|
|
139
|
+
| `mcp env` | Print required/recommended env vars, hosted endpoints, local prerequisites, and setup commands for selected servers. |
|
|
121
140
|
| `mcp enable` | Enable an MCP server in project records and generated snippets. |
|
|
122
141
|
| `mcp disable` | Remove an MCP server from project records and generated snippets. |
|
|
123
142
|
| `mcp install` | Run finite external tool install commands for selected MCP servers. It must not launch stdio MCP servers. |
|
|
124
143
|
| `mcp uninstall` | Run the external uninstall command when one exists. |
|
|
125
|
-
| `mcp
|
|
144
|
+
| `mcp smoke` | Print non-launching readiness diagnostics for enabled or selected MCP servers. |
|
|
145
|
+
| `mcp doctor` | Validate enabled MCP records, generated snippets, required env vars, and documented manual prerequisites. |
|
|
126
146
|
|
|
127
147
|
## Companion Skills
|
|
128
148
|
|
|
@@ -147,11 +167,37 @@ Preset intent:
|
|
|
147
167
|
| Preset | Intent |
|
|
148
168
|
|---|---|
|
|
149
169
|
| `minimal` | Academic research skills only, no MCP records. |
|
|
150
|
-
| `default` | Academic research skills plus
|
|
170
|
+
| `default` | Academic research skills plus the low-friction arXiv MCP record. |
|
|
151
171
|
| `enhanced` | `default` plus curated external complementary skill bundles. |
|
|
152
|
-
| `literature` | SOTA and systematic-review work with
|
|
153
|
-
| `writing` | Paper-writing
|
|
154
|
-
| `full` | Broad
|
|
172
|
+
| `literature` | SOTA and systematic-review work with arXiv plus DBLP for computer science bibliography. |
|
|
173
|
+
| `writing` | Paper-writing work; Overleaf is documented as an opt-in credentialed integration. |
|
|
174
|
+
| `full` | Broad setup with low-friction arXiv and DBLP records plus the full optional MCP catalog documented. |
|
|
175
|
+
|
|
176
|
+
MCP defaults are intentionally conservative. Semantic Scholar, OpenAlex,
|
|
177
|
+
Zotero, Overleaf, Crossref, and fallback aggregators are useful, but they need
|
|
178
|
+
API keys, local apps, manual setup, or source-policy review. Enable them with
|
|
179
|
+
`npx academic-research mcp enable <server>` after reading
|
|
180
|
+
`docs/agent/mcp-setup.md`, use `npx academic-research mcp env <server>` to see
|
|
181
|
+
runtime prerequisites, then run `npx academic-research mcp doctor`.
|
|
182
|
+
|
|
183
|
+
The MCP catalog distinguishes local runtime adapters from hosted endpoints and
|
|
184
|
+
manual integrations. arXiv and DBLP are low-friction local `uvx` runtimes.
|
|
185
|
+
Semantic Scholar is useful for citation graphs but works best with
|
|
186
|
+
`SEMANTIC_SCHOLAR_API_KEY`. OpenAlex requires `OPENALEX_API_KEY` for the
|
|
187
|
+
selected local adapter; OpenAlex keys are free for normal academic use with
|
|
188
|
+
daily free usage. PubMed is a biomedical-specific `npx` runtime and remains
|
|
189
|
+
opt-in. Zotero needs the local Zotero desktop app and Zoty setup. Overleaf is
|
|
190
|
+
manual and credentialed. Crossref and broad paper-search aggregators are kept
|
|
191
|
+
as fallback/manual entries until a project explicitly needs them.
|
|
192
|
+
|
|
193
|
+
Generated MCP snippets are project documentation and client-ready config, not
|
|
194
|
+
live tools by themselves. Your MCP client must load the generated snippet, and
|
|
195
|
+
the referenced commands must be available on your machine or runnable through
|
|
196
|
+
`uvx`/`npx`. `mcp install` only runs finite setup commands such as the arXiv
|
|
197
|
+
tool install; it deliberately does not launch stdio MCP servers.
|
|
198
|
+
Use `mcp smoke` for a non-launching readiness pass before wiring a client: it
|
|
199
|
+
checks required env vars, manual/local-service status, and whether runtime
|
|
200
|
+
commands are visible on `PATH`.
|
|
155
201
|
|
|
156
202
|
## Validate This Package
|
|
157
203
|
|
|
@@ -169,8 +215,8 @@ Releases are tag-driven. Update `package.json` and `package-lock.json`, commit
|
|
|
169
215
|
the change, create `vX.Y.Z`, and push the tag:
|
|
170
216
|
|
|
171
217
|
```bash
|
|
172
|
-
git tag -a v0.1.
|
|
173
|
-
git push origin main v0.1.
|
|
218
|
+
git tag -a v0.1.7 -m "v0.1.7"
|
|
219
|
+
git push origin main v0.1.7
|
|
174
220
|
```
|
|
175
221
|
|
|
176
222
|
Once the GitHub repository is public, the release workflow validates the tag
|
package/dist/src/capabilities.js
CHANGED
|
@@ -25,6 +25,7 @@ export async function writeCapabilities(root, state) {
|
|
|
25
25
|
};
|
|
26
26
|
await writeFile(join(root, "configs/capabilities.yaml"), YAML.stringify(next), "utf8");
|
|
27
27
|
await writeCapabilityProfile(root, next);
|
|
28
|
+
await writeMcpSetup(root, next);
|
|
28
29
|
await writeMcpSnippet(root, next);
|
|
29
30
|
await appendCapabilityLog(root, next);
|
|
30
31
|
}
|
|
@@ -233,6 +234,19 @@ export async function doctorMcpServers(root) {
|
|
|
233
234
|
const server = AGENT_STACK.mcp_servers[name];
|
|
234
235
|
if (!server)
|
|
235
236
|
continue;
|
|
237
|
+
for (const envName of server.required_env) {
|
|
238
|
+
if (!process.env[envName]) {
|
|
239
|
+
errors.push(`${name}: missing required environment variable: ${envName}`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
for (const envName of server.recommended_env) {
|
|
243
|
+
if (!process.env[envName]) {
|
|
244
|
+
warnings.push(`${name}: recommended environment variable not set: ${envName}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (server.local_service) {
|
|
248
|
+
warnings.push(`${name}: requires local service: ${server.local_service}`);
|
|
249
|
+
}
|
|
236
250
|
if (!server.command) {
|
|
237
251
|
warnings.push(`${name}: manual setup only; no generated client command`);
|
|
238
252
|
continue;
|
|
@@ -240,9 +254,6 @@ export async function doctorMcpServers(root) {
|
|
|
240
254
|
if (!generatedServers.has(name)) {
|
|
241
255
|
errors.push(`${name}: enabled but missing from generated MCP snippet`);
|
|
242
256
|
}
|
|
243
|
-
if (!server.install_command) {
|
|
244
|
-
warnings.push(`${name}: no automated install command is defined`);
|
|
245
|
-
}
|
|
246
257
|
}
|
|
247
258
|
return { ok: errors.length === 0, errors, warnings, enabled };
|
|
248
259
|
}
|
|
@@ -290,13 +301,46 @@ async function writeCapabilityProfile(root, state) {
|
|
|
290
301
|
else {
|
|
291
302
|
for (const name of state.mcp_servers) {
|
|
292
303
|
const server = AGENT_STACK.mcp_servers[name];
|
|
293
|
-
const status = server?.command ?
|
|
304
|
+
const status = server?.command ? server.execution_mode : "manual setup";
|
|
294
305
|
lines.push(`- \`${name}\` (${status}): ${server?.smoke_test ?? "Smoke-test before use."}`);
|
|
295
306
|
}
|
|
296
307
|
}
|
|
297
308
|
lines.push("", "## Rules", "", "- Skill installation is project-local by default.", "- Agent target `universal` installs one shared project-local `.agents/skills` copy.", "- MCP enable/disable changes project records; install/uninstall changes external tools.", "- Keep API keys, tokens, cookies, and browser sessions out of git.", "- Cite repository source records, not raw MCP output alone.", "");
|
|
298
309
|
await writeFile(join(root, "docs/agent/capability-profile.md"), lines.join("\n"), "utf8");
|
|
299
310
|
}
|
|
311
|
+
async function writeMcpSetup(root, state) {
|
|
312
|
+
const enabled = new Set(state.mcp_servers ?? []);
|
|
313
|
+
const lines = [
|
|
314
|
+
"# MCP Setup",
|
|
315
|
+
"",
|
|
316
|
+
"This file is generated from the project-local academic research capability stack.",
|
|
317
|
+
"MCP records are configuration snippets and setup guidance; the active MCP client must load the generated snippet before these servers become live tools.",
|
|
318
|
+
"",
|
|
319
|
+
"## Enabled MCP Servers",
|
|
320
|
+
""
|
|
321
|
+
];
|
|
322
|
+
if (enabled.size === 0) {
|
|
323
|
+
lines.push("- None.");
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
for (const name of state.mcp_servers) {
|
|
327
|
+
const server = AGENT_STACK.mcp_servers[name];
|
|
328
|
+
if (!server)
|
|
329
|
+
continue;
|
|
330
|
+
lines.push(`- \`${name}\` (${server.readiness}, ${server.priority}): ${server.source_need}`, ` - Source: \`${server.source}\``, ` - Execution mode: \`${server.execution_mode}\``, ...(server.hosted_url ? [` - Hosted endpoint: <${server.hosted_url}>`] : []), ` - Runtime: ${formatRuntime(server.command, server.args)}`, ` - Install command: ${server.install_command ? `\`${server.install_command}\`` : "none; runtime-only or manual setup"}`, ...server.setup_commands.map((command) => ` - Setup command: \`${command}\``), ` - Smoke test: ${server.smoke_test}`, ` - Risks: ${server.risks}`);
|
|
331
|
+
appendMcpPrerequisiteLines(lines, server.required_env, server.recommended_env, server.local_service);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
lines.push("", "## Available MCP Catalog", "");
|
|
335
|
+
for (const [name, server] of Object.entries(AGENT_STACK.mcp_servers)) {
|
|
336
|
+
const status = enabled.has(name) ? "enabled" : "available";
|
|
337
|
+
lines.push(`- \`${name}\` (${status}, ${server.readiness}, ${server.priority}): ${server.source_need}`, ` - Source: \`${server.source}\``, ` - Execution mode: \`${server.execution_mode}\``, ...(server.hosted_url ? [` - Hosted endpoint: <${server.hosted_url}>`] : []), ...server.setup_commands.map((command) => ` - Setup command: \`${command}\``));
|
|
338
|
+
appendMcpPrerequisiteLines(lines, server.required_env, server.recommended_env, server.local_service);
|
|
339
|
+
}
|
|
340
|
+
lines.push("", "## Operating Rules", "", "- Keep secrets in your shell, MCP client secret store, or local untracked files; do not commit tokens or API keys.", "- Prefer the smallest enabled MCP set that covers the current research question.", "- Treat MCP output as retrieval metadata. Promote claims into repository source records only after source ingestion and citation audit.", "- Run `npx academic-research mcp doctor` after changing MCP records or environment variables.", "");
|
|
341
|
+
await mkdir(join(root, "docs/agent"), { recursive: true });
|
|
342
|
+
await writeFile(join(root, "docs/agent/mcp-setup.md"), lines.join("\n"), "utf8");
|
|
343
|
+
}
|
|
300
344
|
async function appendCapabilityLog(root, state) {
|
|
301
345
|
const logPath = join(root, "wiki/log.md");
|
|
302
346
|
const date = new Date().toISOString().slice(0, 10);
|
|
@@ -311,6 +355,20 @@ function renderSkillCommand(command, agent) {
|
|
|
311
355
|
const agentFlag = normalized === AUTO_AGENT ? "" : `--agent '${normalized}'`;
|
|
312
356
|
return command.replaceAll("{agent_flag}", agentFlag).replaceAll("{agent}", normalized);
|
|
313
357
|
}
|
|
358
|
+
function appendMcpPrerequisiteLines(lines, requiredEnv, recommendedEnv, localService) {
|
|
359
|
+
if (requiredEnv.length > 0)
|
|
360
|
+
lines.push(` - Requires env: ${requiredEnv.map((name) => `\`${name}\``).join(", ")}`);
|
|
361
|
+
if (recommendedEnv.length > 0) {
|
|
362
|
+
lines.push(` - Recommended env: ${recommendedEnv.map((name) => `\`${name}\``).join(", ")}`);
|
|
363
|
+
}
|
|
364
|
+
if (localService)
|
|
365
|
+
lines.push(` - Local prerequisite: ${localService}`);
|
|
366
|
+
}
|
|
367
|
+
function formatRuntime(command, args) {
|
|
368
|
+
if (!command)
|
|
369
|
+
return "manual setup";
|
|
370
|
+
return `\`${[command, ...args].join(" ")}\``;
|
|
371
|
+
}
|
|
314
372
|
async function readCapabilitiesFile(root) {
|
|
315
373
|
const path = join(root, "configs/capabilities.yaml");
|
|
316
374
|
return normalizeCapabilityState(YAML.parse(await readFile(path, "utf8")));
|
package/dist/src/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
|
-
import { basename, dirname, join, resolve } from "node:path";
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { basename, delimiter, dirname, join, resolve } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { disableMcpServers, doctorMcpServers, enableMcpServers, DEFAULT_AGENT, installMcpTools, installSkills, listInstalledSkills, mcpToolCommandTexts, readCapabilities, removeSkills, uninstallMcpTools, updateSkills } from "./capabilities.js";
|
|
4
|
+
import { assertKnownMcpServers, disableMcpServers, doctorMcpServers, enableMcpServers, DEFAULT_AGENT, installMcpTools, installSkills, listInstalledSkills, mcpToolCommandTexts, readCapabilities, removeSkills, uninstallMcpTools, updateSkills } from "./capabilities.js";
|
|
5
5
|
import { createProject, doctorProject, renameProject } from "./project.js";
|
|
6
6
|
import { askCreateOptions } from "./prompts.js";
|
|
7
7
|
import { AGENT_STACK, presetMcpServers } from "./stack.js";
|
|
@@ -100,6 +100,8 @@ async function lifecycleMain(argv) {
|
|
|
100
100
|
}
|
|
101
101
|
if (command === "doctor")
|
|
102
102
|
return doctorCommand(argv.slice(1));
|
|
103
|
+
if (command === "setup")
|
|
104
|
+
return setupCommand(argv.slice(1));
|
|
103
105
|
if (command === "rename")
|
|
104
106
|
return renameCommand(argv.slice(1));
|
|
105
107
|
if (command === "agents")
|
|
@@ -125,6 +127,41 @@ async function doctorCommand(argv) {
|
|
|
125
127
|
console.log(`OK: ${root}`);
|
|
126
128
|
return result.ok ? 0 : 1;
|
|
127
129
|
}
|
|
130
|
+
async function setupCommand(argv) {
|
|
131
|
+
const parsed = parseFlags(argv, ROOT_FLAGS);
|
|
132
|
+
if (flagBool(parsed.flags, "help")) {
|
|
133
|
+
printSetupHelp();
|
|
134
|
+
return 0;
|
|
135
|
+
}
|
|
136
|
+
assertNoArguments(parsed.positionals, "setup");
|
|
137
|
+
const root = resolve(flagString(parsed.flags, "root") ?? ".");
|
|
138
|
+
const project = await doctorProject(root);
|
|
139
|
+
const state = await readCapabilities(root);
|
|
140
|
+
const skills = await listInstalledSkills(root);
|
|
141
|
+
const skillIds = new Set(skills.map((skill) => skill.name));
|
|
142
|
+
console.log("Project Setup");
|
|
143
|
+
console.log(`root\t${root}`);
|
|
144
|
+
console.log(`doctor\t${project.ok ? "ok" : "error"}`);
|
|
145
|
+
console.log(`agent\t${state.agent}`);
|
|
146
|
+
console.log(`preset\t${state.preset}`);
|
|
147
|
+
console.log(`scope\t${state.scope}`);
|
|
148
|
+
console.log(`installed_skill_ids\t${skillIds.size}`);
|
|
149
|
+
console.log(`installed_skill_copies\t${skills.length}`);
|
|
150
|
+
console.log(`mcp_enabled\t${state.mcp_servers.length > 0 ? state.mcp_servers.join(",") : "none"}`);
|
|
151
|
+
if (!project.ok) {
|
|
152
|
+
for (const error of project.errors)
|
|
153
|
+
console.error(`ERROR: ${error}`);
|
|
154
|
+
}
|
|
155
|
+
console.log("");
|
|
156
|
+
console.log("Next Commands");
|
|
157
|
+
console.log(`academic-research skills install --preset ${state.preset}`);
|
|
158
|
+
console.log("academic-research skills status");
|
|
159
|
+
console.log("academic-research mcp list");
|
|
160
|
+
console.log("academic-research mcp env");
|
|
161
|
+
console.log("academic-research mcp smoke");
|
|
162
|
+
console.log("academic-research doctor");
|
|
163
|
+
return project.ok ? 0 : 1;
|
|
164
|
+
}
|
|
128
165
|
async function renameCommand(argv) {
|
|
129
166
|
const parsed = parseFlags(argv, RENAME_FLAGS);
|
|
130
167
|
if (flagBool(parsed.flags, "help")) {
|
|
@@ -244,10 +281,10 @@ async function mcpCommand(argv) {
|
|
|
244
281
|
assertNoArguments(parsed.positionals, "mcp list");
|
|
245
282
|
const state = await readCapabilities(root);
|
|
246
283
|
const enabled = new Set(state.mcp_servers ?? []);
|
|
284
|
+
console.log("status\tid\treadiness\texecution_mode\tdescription");
|
|
247
285
|
for (const [name, server] of Object.entries(AGENT_STACK.mcp_servers)) {
|
|
248
286
|
const status = enabled.has(name) ? "enabled" : "available";
|
|
249
|
-
|
|
250
|
-
console.log(`${status}\t${name}\t${server.source_need}\t${installer}`);
|
|
287
|
+
console.log(`${status}\t${name}\t${server.readiness}\t${server.execution_mode}\t${server.source_need}`);
|
|
251
288
|
}
|
|
252
289
|
return 0;
|
|
253
290
|
}
|
|
@@ -263,9 +300,9 @@ async function mcpCommand(argv) {
|
|
|
263
300
|
if (subcommand === "available") {
|
|
264
301
|
assertOnlyOptions(parsed.flags, "mcp available", []);
|
|
265
302
|
assertNoArguments(parsed.positionals, "mcp available");
|
|
303
|
+
console.log("id\treadiness\texecution_mode\tdescription");
|
|
266
304
|
for (const [name, server] of Object.entries(AGENT_STACK.mcp_servers)) {
|
|
267
|
-
|
|
268
|
-
console.log(`${name}\t${server.source_need}\t${installer}`);
|
|
305
|
+
console.log(`${name}\t${server.readiness}\t${server.execution_mode}\t${server.source_need}`);
|
|
269
306
|
}
|
|
270
307
|
return 0;
|
|
271
308
|
}
|
|
@@ -278,6 +315,15 @@ async function mcpCommand(argv) {
|
|
|
278
315
|
console.log(command);
|
|
279
316
|
return 0;
|
|
280
317
|
}
|
|
318
|
+
if (subcommand === "env") {
|
|
319
|
+
assertOnlyOptions(parsed.flags, "mcp env", ["root"]);
|
|
320
|
+
const root = resolve(flagString(parsed.flags, "root") ?? ".");
|
|
321
|
+
const selected = parsed.positionals.length > 0 ? parsed.positionals : (await readCapabilities(root)).mcp_servers;
|
|
322
|
+
assertKnownMcpServers(selected);
|
|
323
|
+
console.log("id\ttype\tvalue");
|
|
324
|
+
printMcpEnvironment(selected);
|
|
325
|
+
return 0;
|
|
326
|
+
}
|
|
281
327
|
if (subcommand === "enable") {
|
|
282
328
|
assertOnlyOptions(parsed.flags, "mcp enable", ["root", "agent"]);
|
|
283
329
|
const root = resolve(flagString(parsed.flags, "root") ?? ".");
|
|
@@ -308,6 +354,24 @@ async function mcpCommand(argv) {
|
|
|
308
354
|
console.log(`Ran ${result.count ?? 0} MCP uninstall command(s).`);
|
|
309
355
|
return 0;
|
|
310
356
|
}
|
|
357
|
+
if (subcommand === "smoke") {
|
|
358
|
+
assertOnlyOptions(parsed.flags, "mcp smoke", ["root"]);
|
|
359
|
+
const root = resolve(flagString(parsed.flags, "root") ?? ".");
|
|
360
|
+
const state = await readCapabilities(root);
|
|
361
|
+
const explicitSelection = parsed.positionals.length > 0;
|
|
362
|
+
const selected = explicitSelection ? parsed.positionals : state.mcp_servers;
|
|
363
|
+
assertKnownMcpServers(selected);
|
|
364
|
+
const failed = printMcpSmokeDiagnostics(selected);
|
|
365
|
+
if (!explicitSelection) {
|
|
366
|
+
const result = await doctorMcpServers(root);
|
|
367
|
+
for (const error of result.errors)
|
|
368
|
+
console.error(`ERROR: ${error}`);
|
|
369
|
+
for (const warning of result.warnings)
|
|
370
|
+
console.warn(`WARN: ${warning}`);
|
|
371
|
+
return result.ok && !failed ? 0 : 1;
|
|
372
|
+
}
|
|
373
|
+
return failed ? 1 : 0;
|
|
374
|
+
}
|
|
311
375
|
if (subcommand === "doctor") {
|
|
312
376
|
assertOnlyOptions(parsed.flags, "mcp doctor", ["root"]);
|
|
313
377
|
const root = resolve(flagString(parsed.flags, "root") ?? ".");
|
|
@@ -405,11 +469,6 @@ function assertOnlyOptions(flags, command, allowedOptions) {
|
|
|
405
469
|
throw new Error(`${command} does not accept ${unexpected.map((name) => `--${name}`).join(", ")}`);
|
|
406
470
|
}
|
|
407
471
|
}
|
|
408
|
-
function mcpInstallMode(installCommand, runtimeCommand) {
|
|
409
|
-
if (installCommand)
|
|
410
|
-
return installCommand;
|
|
411
|
-
return runtimeCommand ? "runtime-only" : "manual";
|
|
412
|
-
}
|
|
413
472
|
export function formatInteractiveCreateGuide() {
|
|
414
473
|
const presetLines = Object.entries(AGENT_STACK.presets).map(([name, preset]) => ` ${name.padEnd(10)} ${preset.description}`);
|
|
415
474
|
return [
|
|
@@ -432,8 +491,11 @@ export function formatInteractiveCreateGuide() {
|
|
|
432
491
|
"Skill and MCP behavior:",
|
|
433
492
|
" Skills are copied into the project, not installed globally.",
|
|
434
493
|
" MCP records are written into configs/capabilities.yaml and docs/agent/generated/.",
|
|
494
|
+
" docs/agent/mcp-setup.md records enabled servers, optional catalog entries, env vars, and smoke tests.",
|
|
495
|
+
" default enables only low-friction arXiv; credentialed/local services are opt-in.",
|
|
435
496
|
" MCP installers are optional and run only finite installer commands.",
|
|
436
|
-
"
|
|
497
|
+
" MCP execution modes are explicit: uvx-runtime, npx-runtime, local-service, manual, or fallback.",
|
|
498
|
+
" Use `academic-research mcp env <server>` to inspect env vars and local prerequisites.",
|
|
437
499
|
""
|
|
438
500
|
].join("\n");
|
|
439
501
|
}
|
|
@@ -469,7 +531,7 @@ function printMissingTargetHelp() {
|
|
|
469
531
|
}
|
|
470
532
|
function printLifecycleHelp() {
|
|
471
533
|
console.log([
|
|
472
|
-
"Usage: academic-research <doctor|rename|agents|skills|mcp>",
|
|
534
|
+
"Usage: academic-research <doctor|setup|rename|agents|skills|mcp>",
|
|
473
535
|
"",
|
|
474
536
|
"Manage a generated academic research repository after creation.",
|
|
475
537
|
"",
|
|
@@ -478,6 +540,17 @@ function printLifecycleHelp() {
|
|
|
478
540
|
" -v, --version Show package version."
|
|
479
541
|
].join("\n"));
|
|
480
542
|
}
|
|
543
|
+
function printSetupHelp() {
|
|
544
|
+
console.log([
|
|
545
|
+
"Usage: academic-research setup [options]",
|
|
546
|
+
"",
|
|
547
|
+
"Print project onboarding status and next commands without changing files.",
|
|
548
|
+
"",
|
|
549
|
+
"Options:",
|
|
550
|
+
" --root <path> Project root. Default: current directory.",
|
|
551
|
+
" -h, --help Show this help."
|
|
552
|
+
].join("\n"));
|
|
553
|
+
}
|
|
481
554
|
function printAgentsHelp() {
|
|
482
555
|
console.log([
|
|
483
556
|
"Usage: academic-research agents <list>",
|
|
@@ -508,9 +581,9 @@ function printSkillsHelp() {
|
|
|
508
581
|
}
|
|
509
582
|
function printMcpHelp() {
|
|
510
583
|
console.log([
|
|
511
|
-
"Usage: academic-research mcp <list|enabled|available|commands|enable|disable|install|uninstall|doctor> [servers...]",
|
|
584
|
+
"Usage: academic-research mcp <list|enabled|available|commands|env|enable|disable|install|uninstall|smoke|doctor> [servers...]",
|
|
512
585
|
"",
|
|
513
|
-
"Manage MCP records and finite external MCP tool installs.",
|
|
586
|
+
"Manage MCP records, readiness checks, and finite external MCP tool installs.",
|
|
514
587
|
"",
|
|
515
588
|
"Options:",
|
|
516
589
|
" --root <path> Project root for project-state commands.",
|
|
@@ -518,6 +591,79 @@ function printMcpHelp() {
|
|
|
518
591
|
" -h, --help Show this help."
|
|
519
592
|
].join("\n"));
|
|
520
593
|
}
|
|
594
|
+
function printMcpSmokeDiagnostics(servers) {
|
|
595
|
+
let failed = false;
|
|
596
|
+
console.log("id\tstatus\truntime\tcheck");
|
|
597
|
+
for (const name of servers) {
|
|
598
|
+
const server = AGENT_STACK.mcp_servers[name];
|
|
599
|
+
const missingRequired = server.required_env.filter((envName) => !process.env[envName]);
|
|
600
|
+
if (missingRequired.length > 0)
|
|
601
|
+
failed = true;
|
|
602
|
+
const runtime = server.command ? [server.command, ...server.args].join(" ") : "manual setup";
|
|
603
|
+
let status = "manual";
|
|
604
|
+
if (missingRequired.length > 0) {
|
|
605
|
+
status = `missing-required-env:${missingRequired.join(",")}`;
|
|
606
|
+
}
|
|
607
|
+
else if (server.command && commandExists(server.command)) {
|
|
608
|
+
status = "runtime-found";
|
|
609
|
+
}
|
|
610
|
+
else if (server.command) {
|
|
611
|
+
status = "runtime-missing";
|
|
612
|
+
}
|
|
613
|
+
else if (server.local_service) {
|
|
614
|
+
status = "manual-local-service";
|
|
615
|
+
}
|
|
616
|
+
console.log(`${name}\t${status}\t${runtime}\t${server.smoke_test}`);
|
|
617
|
+
}
|
|
618
|
+
return failed;
|
|
619
|
+
}
|
|
620
|
+
function printMcpEnvironment(servers) {
|
|
621
|
+
for (const name of servers) {
|
|
622
|
+
const server = AGENT_STACK.mcp_servers[name];
|
|
623
|
+
let wroteLine = false;
|
|
624
|
+
for (const envName of server.required_env) {
|
|
625
|
+
console.log(`${name}\trequired\t${envName}`);
|
|
626
|
+
wroteLine = true;
|
|
627
|
+
}
|
|
628
|
+
for (const envName of server.recommended_env) {
|
|
629
|
+
console.log(`${name}\trecommended\t${envName}`);
|
|
630
|
+
wroteLine = true;
|
|
631
|
+
}
|
|
632
|
+
if (server.hosted_url) {
|
|
633
|
+
console.log(`${name}\thosted-endpoint\t${server.hosted_url}`);
|
|
634
|
+
wroteLine = true;
|
|
635
|
+
}
|
|
636
|
+
if (server.local_service) {
|
|
637
|
+
console.log(`${name}\tlocal-service\t${server.local_service}`);
|
|
638
|
+
wroteLine = true;
|
|
639
|
+
}
|
|
640
|
+
for (const command of server.setup_commands) {
|
|
641
|
+
console.log(`${name}\tsetup-command\t${command}`);
|
|
642
|
+
wroteLine = true;
|
|
643
|
+
}
|
|
644
|
+
if (!wroteLine)
|
|
645
|
+
console.log(`${name}\tnone\t-`);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
function commandExists(command) {
|
|
649
|
+
if (!command)
|
|
650
|
+
return false;
|
|
651
|
+
if (command.includes("/") || command.includes("\\"))
|
|
652
|
+
return existsSync(command);
|
|
653
|
+
const pathValue = process.env.PATH ?? "";
|
|
654
|
+
const extensions = process.platform === "win32"
|
|
655
|
+
? (process.env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";")
|
|
656
|
+
: [""];
|
|
657
|
+
for (const directory of pathValue.split(delimiter).filter(Boolean)) {
|
|
658
|
+
for (const extension of extensions) {
|
|
659
|
+
const hasExtension = extension && command.toLowerCase().endsWith(extension.toLowerCase());
|
|
660
|
+
const candidate = join(directory, hasExtension ? command : `${command}${extension}`);
|
|
661
|
+
if (existsSync(candidate))
|
|
662
|
+
return true;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
return false;
|
|
666
|
+
}
|
|
521
667
|
function readPackageVersion() {
|
|
522
668
|
try {
|
|
523
669
|
const packageJson = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8"));
|
package/dist/src/project.js
CHANGED
|
@@ -136,11 +136,19 @@ export async function doctorProject(root) {
|
|
|
136
136
|
"configs/agent-stack.yaml",
|
|
137
137
|
"configs/capabilities.yaml",
|
|
138
138
|
"docs/agent/capability-profile.md",
|
|
139
|
+
"docs/agent/mcp-setup.md",
|
|
139
140
|
"docs/agent/generated",
|
|
141
|
+
"scripts/README.md",
|
|
140
142
|
"sources/source-ledger.csv",
|
|
141
143
|
"sota/literature-matrix.csv",
|
|
142
144
|
"wiki/index.md",
|
|
143
|
-
"wiki/log.md"
|
|
145
|
+
"wiki/log.md",
|
|
146
|
+
"wiki/templates/source-page.md",
|
|
147
|
+
"wiki/templates/claim-page.md",
|
|
148
|
+
"wiki/templates/experiment-page.md",
|
|
149
|
+
"wiki/templates/decision-record.md",
|
|
150
|
+
"wiki/templates/reviewer-concern.md",
|
|
151
|
+
"wiki/templates/research-question.md"
|
|
144
152
|
];
|
|
145
153
|
for (const relative of required) {
|
|
146
154
|
if (!(await exists(join(target, relative))))
|
|
@@ -206,7 +214,7 @@ async function writeGeneratedPackageJson(root, { slug }) {
|
|
|
206
214
|
const path = join(root, "package.json");
|
|
207
215
|
const data = await readJson(path);
|
|
208
216
|
const existingSpec = data.devDependencies?.["create-academic-research"];
|
|
209
|
-
const packageSpec = process.env.CREATE_ACADEMIC_RESEARCH_PACKAGE_SPEC ?? existingSpec ?? "0.1.
|
|
217
|
+
const packageSpec = process.env.CREATE_ACADEMIC_RESEARCH_PACKAGE_SPEC ?? existingSpec ?? "0.1.7";
|
|
210
218
|
data.name = slug;
|
|
211
219
|
data.devDependencies = {
|
|
212
220
|
...(data.devDependencies ?? {}),
|
package/dist/src/prompts.js
CHANGED
|
@@ -9,7 +9,8 @@ export async function askCreateOptions(defaults, locks = {}) {
|
|
|
9
9
|
const preset = await question(rl, "Capability preset", defaults.preset);
|
|
10
10
|
const agent = await question(rl, "Agent target", defaults.agent);
|
|
11
11
|
const installSkills = locks.installSkills ?? (await yesNo(rl, "Install project-local skills now", defaults.installSkills));
|
|
12
|
-
const installMcpTools = locks.installMcpTools ??
|
|
12
|
+
const installMcpTools = locks.installMcpTools ??
|
|
13
|
+
(await yesNo(rl, "Run finite external MCP tool installers now", defaults.installMcpTools));
|
|
13
14
|
return { title, slug, packageName, preset, agent, installSkills, installMcpTools };
|
|
14
15
|
}
|
|
15
16
|
finally {
|
package/dist/src/stack.d.ts
CHANGED
|
@@ -8,13 +8,21 @@ export interface CapabilityPreset {
|
|
|
8
8
|
mcp_servers: string[];
|
|
9
9
|
}
|
|
10
10
|
export interface McpServer {
|
|
11
|
+
readiness: string;
|
|
11
12
|
priority: string;
|
|
13
|
+
execution_mode: string;
|
|
12
14
|
source_need: string;
|
|
15
|
+
source: string;
|
|
16
|
+
hosted_url: string;
|
|
13
17
|
install_command: string;
|
|
14
18
|
uninstall_command: string;
|
|
19
|
+
setup_commands: string[];
|
|
15
20
|
command: string;
|
|
16
21
|
args: string[];
|
|
17
22
|
env: Record<string, string>;
|
|
23
|
+
required_env: string[];
|
|
24
|
+
recommended_env: string[];
|
|
25
|
+
local_service: string;
|
|
18
26
|
smoke_test: string;
|
|
19
27
|
risks: string;
|
|
20
28
|
}
|
package/dist/src/stack.js
CHANGED
|
@@ -20,38 +20,6 @@ export const AGENT_STACK = {
|
|
|
20
20
|
commands: [
|
|
21
21
|
"npm exec --yes --package skills -- skills add existential-birds/beagle {agent_flag} --skill docling --copy -y"
|
|
22
22
|
]
|
|
23
|
-
},
|
|
24
|
-
optional_connectors: {
|
|
25
|
-
description: "CLI-side literature connectors to use only when MCP servers are unavailable.",
|
|
26
|
-
commands: [
|
|
27
|
-
"npm exec --yes --package skills -- skills add davila7/claude-code-templates {agent_flag} --skill openalex-database --copy -y",
|
|
28
|
-
"npm exec --yes --package skills -- skills add agents365-ai/365-skills {agent_flag} --skill semanticscholar-skill --copy -y",
|
|
29
|
-
"npm exec --yes --package skills -- skills add fuzhiyu/researchprojecttemplate {agent_flag} --skill zotero-paper-reader --copy -y"
|
|
30
|
-
]
|
|
31
|
-
},
|
|
32
|
-
optional_mechanical_specialists: {
|
|
33
|
-
description: "Narrow mechanical helpers that do not replace project-native governance.",
|
|
34
|
-
commands: [
|
|
35
|
-
"npm exec --yes --package skills -- skills add bahayonghang/academic-writing-skills {agent_flag} --skill latex-paper-en --copy -y",
|
|
36
|
-
[
|
|
37
|
-
"npm exec --yes --package skills -- skills add lllllllama/ai-paper-reproduction-skill",
|
|
38
|
-
"{agent_flag}",
|
|
39
|
-
"--skill",
|
|
40
|
-
[
|
|
41
|
-
"ai-research-reproduction",
|
|
42
|
-
"repo-intake-and-plan",
|
|
43
|
-
"env-and-assets-bootstrap",
|
|
44
|
-
"minimal-run-and-audit",
|
|
45
|
-
"paper-context-resolver",
|
|
46
|
-
"analyze-project",
|
|
47
|
-
"safe-debug",
|
|
48
|
-
"run-train",
|
|
49
|
-
"explore-run",
|
|
50
|
-
"explore-code"
|
|
51
|
-
].join(" "),
|
|
52
|
-
"--copy -y"
|
|
53
|
-
].join(" ")
|
|
54
|
-
]
|
|
55
23
|
}
|
|
56
24
|
},
|
|
57
25
|
presets: {
|
|
@@ -61,119 +29,205 @@ export const AGENT_STACK = {
|
|
|
61
29
|
mcp_servers: []
|
|
62
30
|
},
|
|
63
31
|
default: {
|
|
64
|
-
description: "Clean academic research setup with
|
|
32
|
+
description: "Clean academic research setup with the low-friction arXiv MCP record.",
|
|
65
33
|
skill_bundles: ["academic_research"],
|
|
66
|
-
mcp_servers: ["arxiv"
|
|
34
|
+
mcp_servers: ["arxiv"]
|
|
67
35
|
},
|
|
68
36
|
enhanced: {
|
|
69
37
|
description: "Default academic setup plus complementary agent engineering, document, frontend, testing, and doc conversion skills.",
|
|
70
38
|
skill_bundles: ["academic_research", "default_complementary", "docling"],
|
|
71
|
-
mcp_servers: ["arxiv"
|
|
39
|
+
mcp_servers: ["arxiv"]
|
|
72
40
|
},
|
|
73
41
|
literature: {
|
|
74
|
-
description: "Literature-heavy SOTA, survey, scoping, or systematic review setup.",
|
|
42
|
+
description: "Literature-heavy SOTA, survey, scoping, or systematic review setup with CS bibliography support.",
|
|
75
43
|
skill_bundles: ["academic_research", "default_complementary", "docling"],
|
|
76
|
-
mcp_servers: ["arxiv", "
|
|
44
|
+
mcp_servers: ["arxiv", "dblp"]
|
|
77
45
|
},
|
|
78
46
|
writing: {
|
|
79
|
-
description: "Paper-writing
|
|
80
|
-
skill_bundles: [
|
|
81
|
-
|
|
82
|
-
"default_complementary",
|
|
83
|
-
"docling",
|
|
84
|
-
"optional_mechanical_specialists"
|
|
85
|
-
],
|
|
86
|
-
mcp_servers: ["arxiv", "semantic-scholar", "crossref", "overleaf"]
|
|
47
|
+
description: "Paper-writing setup with Overleaf documented as an opt-in credentialed integration.",
|
|
48
|
+
skill_bundles: ["academic_research", "default_complementary", "docling"],
|
|
49
|
+
mcp_servers: ["arxiv"]
|
|
87
50
|
},
|
|
88
51
|
full: {
|
|
89
|
-
description: "Broad setup with
|
|
90
|
-
skill_bundles: [
|
|
91
|
-
|
|
92
|
-
"default_complementary",
|
|
93
|
-
"docling",
|
|
94
|
-
"optional_connectors",
|
|
95
|
-
"optional_mechanical_specialists"
|
|
96
|
-
],
|
|
97
|
-
mcp_servers: ["arxiv", "semantic-scholar", "openalex", "crossref", "pubmed", "zotero", "overleaf"]
|
|
52
|
+
description: "Broad setup with low-friction scholarly MCP records plus the full optional MCP catalog documented.",
|
|
53
|
+
skill_bundles: ["academic_research", "default_complementary", "docling"],
|
|
54
|
+
mcp_servers: ["arxiv", "dblp"]
|
|
98
55
|
}
|
|
99
56
|
},
|
|
100
57
|
mcp_servers: {
|
|
101
58
|
arxiv: {
|
|
59
|
+
readiness: "low-friction",
|
|
102
60
|
priority: "default",
|
|
61
|
+
execution_mode: "uvx-runtime",
|
|
103
62
|
source_need: "arXiv search, download, and local paper reading.",
|
|
63
|
+
source: "blazickjp/arxiv-mcp-server",
|
|
64
|
+
hosted_url: "",
|
|
104
65
|
install_command: "uv tool install 'arxiv-mcp-server[pdf]'",
|
|
105
66
|
uninstall_command: "uv tool uninstall arxiv-mcp-server",
|
|
106
|
-
|
|
107
|
-
|
|
67
|
+
setup_commands: [],
|
|
68
|
+
command: "uvx",
|
|
69
|
+
args: ["--from", "arxiv-mcp-server[pdf]", "arxiv-mcp-server"],
|
|
108
70
|
env: {},
|
|
71
|
+
required_env: [],
|
|
72
|
+
recommended_env: [],
|
|
73
|
+
local_service: "",
|
|
109
74
|
smoke_test: "For a computer science project, search one CS query, download one known paper, and read it locally.",
|
|
110
75
|
risks: "Respect arXiv rate limits; paper text is untrusted input."
|
|
111
76
|
},
|
|
112
77
|
"semantic-scholar": {
|
|
113
|
-
|
|
78
|
+
readiness: "credential-recommended",
|
|
79
|
+
priority: "optional",
|
|
80
|
+
execution_mode: "uvx-runtime",
|
|
114
81
|
source_need: "Semantic Scholar papers, citations, authors, and recommendations.",
|
|
82
|
+
source: "akapet00/semantic-scholar-mcp",
|
|
83
|
+
hosted_url: "",
|
|
115
84
|
install_command: "",
|
|
116
85
|
uninstall_command: "",
|
|
86
|
+
setup_commands: [],
|
|
117
87
|
command: "uvx",
|
|
118
88
|
args: ["--from", "git+https://github.com/akapet00/semantic-scholar-mcp", "semantic-scholar-mcp"],
|
|
119
|
-
env: {
|
|
89
|
+
env: {},
|
|
90
|
+
required_env: [],
|
|
91
|
+
recommended_env: ["SEMANTIC_SCHOLAR_API_KEY"],
|
|
120
92
|
smoke_test: "Search one known title, then fetch citations or references.",
|
|
121
|
-
|
|
93
|
+
local_service: "",
|
|
94
|
+
risks: "API key recommended for sustained work and to avoid shared-pool rate limits; metadata can be incomplete."
|
|
122
95
|
},
|
|
123
96
|
openalex: {
|
|
124
|
-
|
|
97
|
+
readiness: "credential-required",
|
|
98
|
+
priority: "optional",
|
|
99
|
+
execution_mode: "npx-runtime",
|
|
125
100
|
source_need: "OpenAlex broad scholarly graph.",
|
|
101
|
+
source: "cyanheads/openalex-mcp-server",
|
|
102
|
+
hosted_url: "https://openalex.caseyjhand.com/mcp",
|
|
126
103
|
install_command: "",
|
|
127
104
|
uninstall_command: "",
|
|
105
|
+
setup_commands: [],
|
|
128
106
|
command: "npx",
|
|
129
|
-
args: ["-y", "@cyanheads/openalex-mcp-server"],
|
|
130
|
-
env: {
|
|
107
|
+
args: ["-y", "@cyanheads/openalex-mcp-server@latest"],
|
|
108
|
+
env: {},
|
|
109
|
+
required_env: ["OPENALEX_API_KEY"],
|
|
110
|
+
recommended_env: [],
|
|
111
|
+
local_service: "",
|
|
131
112
|
smoke_test: "Search works by title or DOI and confirm stable OpenAlex IDs.",
|
|
132
|
-
risks: "
|
|
113
|
+
risks: "The selected local server requires OPENALEX_API_KEY. OpenAlex keys are free for normal academic use with daily free usage; smoke-test coverage and cost headers before high-volume work."
|
|
133
114
|
},
|
|
134
115
|
crossref: {
|
|
116
|
+
readiness: "manual",
|
|
135
117
|
priority: "manual",
|
|
118
|
+
execution_mode: "manual",
|
|
136
119
|
source_need: "DOI and publication metadata.",
|
|
120
|
+
source: "manual selection required; candidate: AiAgentKarl/crossref-academic-mcp-server",
|
|
121
|
+
hosted_url: "",
|
|
137
122
|
install_command: "",
|
|
138
123
|
uninstall_command: "",
|
|
124
|
+
setup_commands: [],
|
|
139
125
|
command: "",
|
|
140
126
|
args: [],
|
|
141
127
|
env: {},
|
|
128
|
+
required_env: [],
|
|
129
|
+
recommended_env: [],
|
|
130
|
+
local_service: "",
|
|
142
131
|
smoke_test: "Resolve one DOI into publication metadata after choosing a maintained local server.",
|
|
143
|
-
risks: "Manual integration only;
|
|
132
|
+
risks: "Manual integration only; current zero-friction Crossref-only MCP candidates are less mature than arXiv, DBLP, PubMed, or OpenAlex."
|
|
144
133
|
},
|
|
145
134
|
pubmed: {
|
|
135
|
+
readiness: "domain-specific",
|
|
146
136
|
priority: "domain-specific",
|
|
137
|
+
execution_mode: "npx-runtime",
|
|
147
138
|
source_need: "PubMed and biomedical literature.",
|
|
139
|
+
source: "cyanheads/pubmed-mcp-server",
|
|
140
|
+
hosted_url: "https://pubmed.caseyjhand.com/mcp",
|
|
148
141
|
install_command: "",
|
|
149
142
|
uninstall_command: "",
|
|
143
|
+
setup_commands: [],
|
|
150
144
|
command: "npx",
|
|
151
|
-
args: ["-y", "@cyanheads/pubmed-mcp-server"],
|
|
152
|
-
env: {
|
|
145
|
+
args: ["-y", "@cyanheads/pubmed-mcp-server@latest"],
|
|
146
|
+
env: { MCP_TRANSPORT_TYPE: "stdio", MCP_LOG_LEVEL: "warning" },
|
|
147
|
+
required_env: [],
|
|
148
|
+
recommended_env: ["NCBI_API_KEY", "NCBI_ADMIN_EMAIL"],
|
|
149
|
+
local_service: "",
|
|
153
150
|
smoke_test: "Search one PMID or title and fetch metadata.",
|
|
154
|
-
risks: "Domain-specific; observe NCBI rate limits."
|
|
151
|
+
risks: "Domain-specific; observe NCBI rate limits. API key and contact email improve reliability."
|
|
152
|
+
},
|
|
153
|
+
dblp: {
|
|
154
|
+
readiness: "low-friction-cs",
|
|
155
|
+
priority: "cs",
|
|
156
|
+
execution_mode: "uvx-runtime",
|
|
157
|
+
source_need: "DBLP computer science bibliography, venues, authors, and BibTeX.",
|
|
158
|
+
source: "szeider/mcp-dblp",
|
|
159
|
+
hosted_url: "",
|
|
160
|
+
install_command: "",
|
|
161
|
+
uninstall_command: "",
|
|
162
|
+
setup_commands: [],
|
|
163
|
+
command: "uvx",
|
|
164
|
+
args: ["mcp-dblp"],
|
|
165
|
+
env: {},
|
|
166
|
+
required_env: [],
|
|
167
|
+
recommended_env: [],
|
|
168
|
+
local_service: "",
|
|
169
|
+
smoke_test: "Search one known CS paper title and export or inspect its DBLP BibTeX.",
|
|
170
|
+
risks: "CS-specific metadata source; use with arXiv/Semantic Scholar/OpenAlex for coverage beyond DBLP."
|
|
155
171
|
},
|
|
156
172
|
zotero: {
|
|
173
|
+
readiness: "local-service",
|
|
157
174
|
priority: "local-library",
|
|
175
|
+
execution_mode: "local-service",
|
|
158
176
|
source_need: "Zotero local library and attachments.",
|
|
177
|
+
source: "eric-tramel/zoty",
|
|
178
|
+
hosted_url: "",
|
|
159
179
|
install_command: "",
|
|
160
180
|
uninstall_command: "",
|
|
181
|
+
setup_commands: ["uvx --refresh zoty setup", "uvx --refresh zoty doctor"],
|
|
161
182
|
command: "uvx",
|
|
162
183
|
args: ["zoty", "mcp"],
|
|
163
184
|
env: {},
|
|
185
|
+
required_env: [],
|
|
186
|
+
recommended_env: [],
|
|
187
|
+
local_service: "Zotero desktop running with local API enabled; Zoty Bridge required for attachment and collection write operations.",
|
|
164
188
|
smoke_test: "List collections, search one known item, and export BibTeX.",
|
|
165
189
|
risks: "Requires Zotero local API and bridge setup."
|
|
166
190
|
},
|
|
167
191
|
overleaf: {
|
|
192
|
+
readiness: "manual-credentialed",
|
|
168
193
|
priority: "writing",
|
|
194
|
+
execution_mode: "manual-local",
|
|
169
195
|
source_need: "Overleaf project sync.",
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
196
|
+
source: "YounesBensafia/overleaf-mcp-server",
|
|
197
|
+
hosted_url: "",
|
|
198
|
+
install_command: "",
|
|
199
|
+
uninstall_command: "",
|
|
200
|
+
setup_commands: [],
|
|
201
|
+
command: "",
|
|
202
|
+
args: [],
|
|
203
|
+
env: {},
|
|
204
|
+
required_env: ["OVERLEAF_TOKEN"],
|
|
205
|
+
recommended_env: ["PROJECT_ID"],
|
|
206
|
+
local_service: "Local clone of the Overleaf MCP server configured with uv and an Overleaf project that supports Git sync.",
|
|
175
207
|
smoke_test: "List projects or read one .tex file; do not write by default.",
|
|
176
|
-
risks: "Requires token setup; write access needs explicit approval."
|
|
208
|
+
risks: "Requires token and project setup; write/push access needs explicit approval."
|
|
209
|
+
},
|
|
210
|
+
"paper-search": {
|
|
211
|
+
readiness: "fallback",
|
|
212
|
+
priority: "fallback",
|
|
213
|
+
execution_mode: "manual-fallback",
|
|
214
|
+
source_need: "Multi-source paper search and download fallback across many scholarly sources.",
|
|
215
|
+
source: "openags/paper-search-mcp",
|
|
216
|
+
hosted_url: "",
|
|
217
|
+
install_command: "",
|
|
218
|
+
uninstall_command: "",
|
|
219
|
+
setup_commands: [],
|
|
220
|
+
command: "",
|
|
221
|
+
args: [],
|
|
222
|
+
env: {},
|
|
223
|
+
required_env: [],
|
|
224
|
+
recommended_env: [
|
|
225
|
+
"PAPER_SEARCH_MCP_UNPAYWALL_EMAIL",
|
|
226
|
+
"PAPER_SEARCH_MCP_SEMANTIC_SCHOLAR_API_KEY"
|
|
227
|
+
],
|
|
228
|
+
local_service: "Manual review required before enabling; configure only permitted sources.",
|
|
229
|
+
smoke_test: "Search one harmless query with a source allow-list and verify provenance for each result.",
|
|
230
|
+
risks: "Powerful aggregator with optional restricted-source workflows; keep Sci-Hub or questionable download features disabled unless explicitly accepted."
|
|
177
231
|
}
|
|
178
232
|
}
|
|
179
233
|
};
|
package/package.json
CHANGED
package/template/AGENTS.md
CHANGED
|
@@ -6,7 +6,8 @@ scholarly record.
|
|
|
6
6
|
## Core Rules
|
|
7
7
|
|
|
8
8
|
- Preserve source originals under `sources/`, `data/raw/`, and `data/external/`.
|
|
9
|
-
- Keep reusable logic in `src/`; keep
|
|
9
|
+
- Keep reusable logic in `src/`; keep `scripts/` as thin repeatable entrypoints.
|
|
10
|
+
- Keep notebooks for exploration and narrative output.
|
|
10
11
|
- Tie claims to sources, datasets, experiment records, or decision records.
|
|
11
12
|
- Update durable records when project knowledge changes.
|
|
12
13
|
- Keep large data, generated caches, credentials, and private review material out of git.
|
|
@@ -35,6 +36,8 @@ scholarly record.
|
|
|
35
36
|
- `wiki/synthesis.md` changes only when the project-level interpretation changes.
|
|
36
37
|
- `wiki/open_questions.md` tracks unresolved questions.
|
|
37
38
|
- `wiki/contradictions.md` tracks conflicts across sources, data, or runs.
|
|
39
|
+
- `wiki/templates/` contains reusable source, claim, experiment, decision,
|
|
40
|
+
reviewer-concern, and research-question page structures.
|
|
38
41
|
|
|
39
42
|
## Evidence
|
|
40
43
|
|
|
@@ -45,3 +48,4 @@ scholarly record.
|
|
|
45
48
|
- Citation issues go in `sources/bib/citation-audit.csv`.
|
|
46
49
|
- SOTA records go in `sota/`.
|
|
47
50
|
- Curated experiment records go in `experiments/`.
|
|
51
|
+
- Repeatable command entrypoints go in `scripts/`.
|
package/template/README.md
CHANGED
|
@@ -41,6 +41,7 @@ npx academic-research doctor
|
|
|
41
41
|
- `docs/agent/`: active agent workflows, capability profile, and MCP setup.
|
|
42
42
|
- `docs/methodology/`: research design, evaluation plan, and validity threats.
|
|
43
43
|
- `experiments/`: curated experiment registry and run records.
|
|
44
|
+
- `scripts/`: thin repeatable entrypoints that call reusable code in `src/`.
|
|
44
45
|
- `notebooks/`: optional exploratory and narrative notebooks.
|
|
45
46
|
- `outputs/`: final figures, tables, models, and paper-supporting derived assets.
|
|
46
47
|
- `reports/`: proposal, paper, slides, reviews, and rebuttal material.
|
|
@@ -58,19 +59,33 @@ npx academic-research skills install --preset default
|
|
|
58
59
|
npx academic-research skills install --preset enhanced
|
|
59
60
|
npx academic-research skills list
|
|
60
61
|
npx academic-research skills status
|
|
61
|
-
npx academic-research
|
|
62
|
+
npx academic-research setup
|
|
62
63
|
npx academic-research mcp list
|
|
64
|
+
npx academic-research mcp env openalex semantic-scholar zotero
|
|
65
|
+
npx academic-research mcp enable arxiv dblp
|
|
63
66
|
npx academic-research mcp commands arxiv
|
|
64
67
|
npx academic-research mcp install arxiv
|
|
68
|
+
npx academic-research mcp smoke
|
|
69
|
+
npx academic-research mcp doctor
|
|
65
70
|
```
|
|
66
71
|
|
|
67
72
|
`skills list` reports installed project-local skills. `skills presets` reports
|
|
68
73
|
available install presets. `mcp enable` changes project records. `mcp commands`
|
|
69
|
-
prints finite external install commands without running them. `mcp
|
|
70
|
-
|
|
71
|
-
|
|
74
|
+
prints finite external install commands without running them. `mcp env` prints
|
|
75
|
+
env vars, hosted endpoints, local prerequisites, and setup commands before you
|
|
76
|
+
enable optional servers. `mcp install` runs only finite tool installation
|
|
77
|
+
commands; runtime-only `uvx`/`npx` MCP servers may have no install step and are
|
|
78
|
+
started later by the MCP client.
|
|
79
|
+
|
|
80
|
+
`setup` prints the current project capability state, installed skill counts,
|
|
81
|
+
enabled MCP records, and the next onboarding commands without changing files.
|
|
82
|
+
`mcp smoke` performs a non-launching MCP readiness check: it reports required
|
|
83
|
+
env vars, local/manual setup, and whether client runtime commands such as `uvx`
|
|
84
|
+
or `npx` are available.
|
|
72
85
|
|
|
73
86
|
`default` installs the companion academic research skill package and keeps the
|
|
74
|
-
MCP records focused on
|
|
75
|
-
|
|
76
|
-
|
|
87
|
+
MCP records focused on low-friction arXiv discovery. `literature` and `full`
|
|
88
|
+
add DBLP for computer science bibliography. Credentialed, local-service, or
|
|
89
|
+
domain-specific MCP servers such as OpenAlex, Semantic Scholar, PubMed, Zotero,
|
|
90
|
+
and Overleaf should be enabled only after reading `docs/agent/mcp-setup.md` and
|
|
91
|
+
checking their prerequisites with `mcp env`.
|
package/template/package.json
CHANGED
|
@@ -4,14 +4,17 @@
|
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"doctor": "academic-research doctor",
|
|
7
|
+
"setup": "academic-research setup",
|
|
7
8
|
"skills:install": "academic-research skills install --preset default",
|
|
8
9
|
"skills:list": "academic-research skills list",
|
|
9
10
|
"skills:presets": "academic-research skills presets",
|
|
10
11
|
"mcp:list": "academic-research mcp list",
|
|
11
12
|
"mcp:commands": "academic-research mcp commands",
|
|
13
|
+
"mcp:env": "academic-research mcp env",
|
|
14
|
+
"mcp:smoke": "academic-research mcp smoke",
|
|
12
15
|
"mcp:doctor": "academic-research mcp doctor"
|
|
13
16
|
},
|
|
14
17
|
"devDependencies": {
|
|
15
|
-
"create-academic-research": "0.1.
|
|
18
|
+
"create-academic-research": "0.1.7"
|
|
16
19
|
}
|
|
17
20
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Scripts
|
|
2
|
+
|
|
3
|
+
Use this folder for thin, repeatable command entrypoints.
|
|
4
|
+
|
|
5
|
+
Scripts should orchestrate project code, not contain core scientific logic. Put
|
|
6
|
+
reusable methods, models, data transforms, and analysis functions in `src/`.
|
|
7
|
+
|
|
8
|
+
Each script should make its inputs, outputs, config path, and expected side
|
|
9
|
+
effects clear enough to reproduce later from `docs/reproducibility/` or an
|
|
10
|
+
experiment record.
|
|
@@ -8,6 +8,7 @@ def test_core_research_structure_exists() -> None:
|
|
|
8
8
|
"configs/default.yaml",
|
|
9
9
|
"configs/capabilities.yaml",
|
|
10
10
|
"docs/agent/capability-profile.md",
|
|
11
|
+
"scripts/README.md",
|
|
11
12
|
"notebooks/README.md",
|
|
12
13
|
"outputs/figures",
|
|
13
14
|
"outputs/tables",
|
|
@@ -21,5 +22,11 @@ def test_core_research_structure_exists() -> None:
|
|
|
21
22
|
"sota/literature-matrix.csv",
|
|
22
23
|
"wiki/index.md",
|
|
23
24
|
"wiki/log.md",
|
|
25
|
+
"wiki/templates/source-page.md",
|
|
26
|
+
"wiki/templates/claim-page.md",
|
|
27
|
+
"wiki/templates/experiment-page.md",
|
|
28
|
+
"wiki/templates/decision-record.md",
|
|
29
|
+
"wiki/templates/reviewer-concern.md",
|
|
30
|
+
"wiki/templates/research-question.md",
|
|
24
31
|
):
|
|
25
32
|
assert (root / relative).exists()
|
package/template/wiki/index.md
CHANGED
|
@@ -7,3 +7,12 @@ This is the content index for the LLM-maintained project wiki.
|
|
|
7
7
|
- [[synthesis]]
|
|
8
8
|
- [[open_questions]]
|
|
9
9
|
- [[contradictions]]
|
|
10
|
+
|
|
11
|
+
## Templates
|
|
12
|
+
|
|
13
|
+
- [[templates/source-page]]
|
|
14
|
+
- [[templates/claim-page]]
|
|
15
|
+
- [[templates/experiment-page]]
|
|
16
|
+
- [[templates/decision-record]]
|
|
17
|
+
- [[templates/reviewer-concern]]
|
|
18
|
+
- [[templates/research-question]]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Claim: <claim_id>
|
|
2
|
+
|
|
3
|
+
## Claim
|
|
4
|
+
|
|
5
|
+
<fill: atomic claim>
|
|
6
|
+
|
|
7
|
+
## Status
|
|
8
|
+
|
|
9
|
+
- Verdict:
|
|
10
|
+
- Confidence:
|
|
11
|
+
- Last checked:
|
|
12
|
+
|
|
13
|
+
## Evidence
|
|
14
|
+
|
|
15
|
+
| source_or_run_id | path | support_span | verdict | notes |
|
|
16
|
+
|---|---|---|---|---|
|
|
17
|
+
|
|
18
|
+
## Safe Wording
|
|
19
|
+
|
|
20
|
+
<fill: wording that current evidence supports>
|
|
21
|
+
|
|
22
|
+
## Risk
|
|
23
|
+
|
|
24
|
+
<fill: what would weaken, falsify, or narrow this claim>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Decision: <decision_id>
|
|
2
|
+
|
|
3
|
+
## Context
|
|
4
|
+
|
|
5
|
+
<fill: situation and constraints>
|
|
6
|
+
|
|
7
|
+
## Decision
|
|
8
|
+
|
|
9
|
+
<fill: chosen option>
|
|
10
|
+
|
|
11
|
+
## Alternatives Considered
|
|
12
|
+
|
|
13
|
+
| option | reason rejected |
|
|
14
|
+
|---|---|
|
|
15
|
+
|
|
16
|
+
## Evidence
|
|
17
|
+
|
|
18
|
+
- Sources:
|
|
19
|
+
- Experiments:
|
|
20
|
+
- Reviews:
|
|
21
|
+
|
|
22
|
+
## Consequences
|
|
23
|
+
|
|
24
|
+
- Expected benefit:
|
|
25
|
+
- Risk:
|
|
26
|
+
- Review date:
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Experiment: <run_id>
|
|
2
|
+
|
|
3
|
+
## Question
|
|
4
|
+
|
|
5
|
+
<fill: research question or hypothesis>
|
|
6
|
+
|
|
7
|
+
## Run
|
|
8
|
+
|
|
9
|
+
- Date:
|
|
10
|
+
- Git commit:
|
|
11
|
+
- Command:
|
|
12
|
+
- Config:
|
|
13
|
+
- Seed:
|
|
14
|
+
- Dataset:
|
|
15
|
+
- Metric:
|
|
16
|
+
- Output path:
|
|
17
|
+
|
|
18
|
+
## Result
|
|
19
|
+
|
|
20
|
+
<fill: measured outcome>
|
|
21
|
+
|
|
22
|
+
## Interpretation
|
|
23
|
+
|
|
24
|
+
<fill: claim status, limitations, and next action>
|
|
25
|
+
|
|
26
|
+
## Links
|
|
27
|
+
|
|
28
|
+
- Registry row: `experiments/registry.csv`
|
|
29
|
+
- Related claims:
|
|
30
|
+
- Related sources:
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Research Question: <rq_id>
|
|
2
|
+
|
|
3
|
+
## Question
|
|
4
|
+
|
|
5
|
+
<fill: answerable research question>
|
|
6
|
+
|
|
7
|
+
## Scope
|
|
8
|
+
|
|
9
|
+
- Population/domain:
|
|
10
|
+
- Evidence type:
|
|
11
|
+
- Exclusions:
|
|
12
|
+
|
|
13
|
+
## Contribution Link
|
|
14
|
+
|
|
15
|
+
- Candidate claim:
|
|
16
|
+
- Closest prior work:
|
|
17
|
+
- Delta:
|
|
18
|
+
- Failure condition:
|
|
19
|
+
|
|
20
|
+
## Evidence Plan
|
|
21
|
+
|
|
22
|
+
| evidence_needed | path_or_source | status | risk |
|
|
23
|
+
|---|---|---|---|
|
|
24
|
+
|
|
25
|
+
## Current Status
|
|
26
|
+
|
|
27
|
+
<fill: hypothesis, active, answered, rejected, or out of scope>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Reviewer Concern: <concern_id>
|
|
2
|
+
|
|
3
|
+
## Concern
|
|
4
|
+
|
|
5
|
+
<fill: reviewer or internal-review concern>
|
|
6
|
+
|
|
7
|
+
## Classification
|
|
8
|
+
|
|
9
|
+
- Source:
|
|
10
|
+
- Severity:
|
|
11
|
+
- Paper location:
|
|
12
|
+
- Claim or issue:
|
|
13
|
+
- Action: concede | clarify | add-evidence | reframe | defend | defer
|
|
14
|
+
|
|
15
|
+
## Evidence
|
|
16
|
+
|
|
17
|
+
<fill: source, experiment, or manuscript evidence>
|
|
18
|
+
|
|
19
|
+
## Response Plan
|
|
20
|
+
|
|
21
|
+
<fill: exact response and manuscript change>
|
|
22
|
+
|
|
23
|
+
## Status
|
|
24
|
+
|
|
25
|
+
<fill: open, addressed, deferred, rejected with rationale>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Source: <source_id>
|
|
2
|
+
|
|
3
|
+
## Bibliographic Record
|
|
4
|
+
|
|
5
|
+
- Title:
|
|
6
|
+
- Authors:
|
|
7
|
+
- Year:
|
|
8
|
+
- Venue:
|
|
9
|
+
- Identifiers:
|
|
10
|
+
- Native path:
|
|
11
|
+
- Derived path:
|
|
12
|
+
- Metadata path:
|
|
13
|
+
|
|
14
|
+
## Summary
|
|
15
|
+
|
|
16
|
+
<fill: concise source summary>
|
|
17
|
+
|
|
18
|
+
## Evidence Record
|
|
19
|
+
|
|
20
|
+
- Supports:
|
|
21
|
+
- Contradicts:
|
|
22
|
+
- Method / data / metric:
|
|
23
|
+
- Limitations:
|
|
24
|
+
- Project relevance:
|
|
25
|
+
- Claim strength:
|
|
26
|
+
- Allowed wording:
|
|
27
|
+
- Forbidden stronger wording:
|
|
28
|
+
|
|
29
|
+
## Follow-Up
|
|
30
|
+
|
|
31
|
+
- <fill: unresolved checks>
|
|
File without changes
|