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 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 scholarly MCP records for `arxiv`, `semantic-scholar`, and
50
- `openalex`;
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 enable arxiv openalex
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 doctor` | Validate enabled MCP records and generated snippets. |
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 core scholarly MCP records. |
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 citation-library MCP records. |
153
- | `writing` | Paper-writing and Overleaf-oriented work. |
154
- | `full` | Broad optional connector and specialist setup. |
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.5 -m "v0.1.5"
173
- git push origin main v0.1.5
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
@@ -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 ? "generated config" : "manual setup";
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
- const installer = mcpInstallMode(server.install_command, server.command);
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
- const installer = mcpInstallMode(server.install_command, server.command);
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
- " runtime-only MCP servers are configured for the MCP client but have no install step.",
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"));
@@ -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.5";
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 ?? {}),
@@ -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 ?? (await yesNo(rl, "Run external MCP installers now", defaults.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 {
@@ -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 core scholarly MCP records.",
32
+ description: "Clean academic research setup with the low-friction arXiv MCP record.",
65
33
  skill_bundles: ["academic_research"],
66
- mcp_servers: ["arxiv", "semantic-scholar", "openalex"]
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", "semantic-scholar", "openalex"]
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", "semantic-scholar", "openalex", "crossref", "zotero"]
44
+ mcp_servers: ["arxiv", "dblp"]
77
45
  },
78
46
  writing: {
79
- description: "Paper-writing and Overleaf-oriented setup.",
80
- skill_bundles: [
81
- "academic_research",
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 optional connector and mechanical specialist skills.",
90
- skill_bundles: [
91
- "academic_research",
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
- command: "arxiv-mcp-server",
107
- args: [],
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
- priority: "default",
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: { SEMANTIC_SCHOLAR_API_KEY: "${SEMANTIC_SCHOLAR_API_KEY}" },
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
- risks: "API key recommended for sustained work; metadata can be incomplete."
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
- priority: "default",
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: { OPENALEX_API_KEY: "${OPENALEX_API_KEY_OR_EMAIL}" },
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: "Smoke-test before relying on it for final coverage."
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; do not generate placeholder paths."
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: { NCBI_API_KEY: "${NCBI_API_KEY}" },
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
- install_command: "uv tool install overleaf-mcp-server",
171
- uninstall_command: "uv tool uninstall overleaf-mcp-server",
172
- command: "overleaf-mcp",
173
- args: ["serve"],
174
- env: { OVERLEAF_TOKEN: "${OVERLEAF_TOKEN}" },
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-academic-research",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Create and manage agent-ready academic research repositories.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -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 notebooks for exploration and narrative output.
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/`.
@@ -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 mcp enable arxiv semantic-scholar openalex
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 install`
70
- runs only finite tool installation commands; runtime-only `uvx`/`npx` MCP
71
- servers may have no install step and are started later by the MCP client.
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 core scholarly discovery. `enhanced` adds complementary
75
- external skills for agent engineering, frontend work, testing, document
76
- formats, and PDF conversion.
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`.
@@ -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.5"
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()
@@ -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