Skip to content

fix: MCP server fails to start via npx (#58)#63

Merged
rohitg00 merged 2 commits intomainfrom
fix/mcp-server-symlink-startup
Feb 10, 2026
Merged

fix: MCP server fails to start via npx (#58)#63
rohitg00 merged 2 commits intomainfrom
fix/mcp-server-symlink-startup

Conversation

@rohitg00
Copy link
Copy Markdown
Owner

@rohitg00 rohitg00 commented Feb 10, 2026

Summary

  • Symlink fix: isMain guard used process.argv[1] === fileURLToPath(import.meta.url) which fails when npx creates a .bin/ symlink. Fixed with realpathSync() to resolve both paths before comparison.
  • skills.json bundling: marketplace/skills.json wasn't included in the npm package ("files": ["dist"]). Added prebuild script to copy it to data/ and included data in files array.
  • Version bump: Server version string updated from 1.12.0 to 1.16.0.

Closes #58

Test plan

  • pnpm --filter @skillkit/mcp build succeeds
  • pnpm --filter @skillkit/mcp test — 9/9 tests pass
  • node packages/mcp/dist/index.js — starts and loads 15,065 skills
  • Symlink test: ln -sf .../dist/index.js /tmp/test && node /tmp/test — starts correctly

Open with Devin

Summary by CodeRabbit

  • Chores
    • Updated SkillKit Discovery MCP Server version to 1.16.0
    • Improved skill data loading reliability through enhanced path resolution
    • Ensured data files are included in the package and prebuild now prepares them for distribution
    • Ignored generated build and data directories from version control

1. isMain guard: process.argv[1] (symlink path) never matched
   import.meta.url (real path). Fixed with realpathSync comparison.

2. skills.json not in npm package: prebuild copies marketplace/skills.json
   to data/ dir, included in package files.

3. Version string bumped from 1.12.0 to 1.16.0.

Closes #58
@vercel
Copy link
Copy Markdown

vercel bot commented Feb 10, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
skillkit Ready Ready Preview, Comment Feb 10, 2026 11:10am
skillkit-docs Ready Ready Preview, Comment Feb 10, 2026 11:10am

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 10, 2026

📝 Walkthrough

Walkthrough

Implements symlink-aware entry-point detection using realpathSync and expands skills.json discovery paths; adds a prebuild step to include data/skills.json in the package and updates .gitignore and server version.

Changes

Cohort / File(s) Summary
Build & packaging
packages/mcp/.gitignore, packages/mcp/package.json
Added dist/ and data/ to .gitignore. Added a prebuild script that creates data/ and copies ../../marketplace/skills.json to data/skills.json. Included "data" in the files array so published packages contain the data directory.
Runtime entry & skill loading
packages/mcp/src/index.ts
Imported realpathSync and switched entry-point detection to compare realpaths (symlink-aware) for process.argv[1]. Extended search locations for skills.json (multiple package-relative and process.cwd() paths). Updated server version from 1.12.0 to 1.16.0.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as "CLI (process argv)"
  participant FS as "Filesystem (realpathSync)"
  participant Loader as "MCP loader"
  participant Server as "SkillKit MCP Server"

  CLI->>FS: realpath(process.argv[1])
  FS->>CLI: resolved CLI path (rgba(100,150,250,0.5))
  Loader->>FS: compute pkgDir and candidate paths
  Loader->>FS: check `pkgDir/../data/skills.json`, `pkgDir/../../marketplace/skills.json`, `process.cwd()/marketplace/skills.json`
  FS-->>Loader: return first existing skills.json path (rgba(150,200,100,0.5))
  CLI->>FS: realpath(import.meta.url)
  FS->>CLI: resolved module path (rgba(200,100,150,0.5))
  CLI->>Loader: compare resolved paths -> if equal, invoke main()
  Loader->>Server: start server with loaded skills and version 1.16.0
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I hopped on symlinks, sniffed the trail so fine,
realpath led the way, no more missing line.
I packed the skills in data, neat and spry,
Now npx hears our drum — the server runs, hi! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main issue (MCP server fails to start via npx) and references the linked issue #58, accurately summarizing the primary fix.
Linked Issues check ✅ Passed The PR addresses all three coding objectives from issue #58: fixing the symlink-aware isMain check with realpathSync, bundling skills.json via prebuild script and files array, and updating the version to 1.16.0.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing issue #58: .gitignore entries prevent dist/data from version control, package.json changes bundle skills.json, and index.ts fixes the symlink issue and version number.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/mcp-server-symlink-startup

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
packages/mcp/src/index.ts (1)

4-4: Nit: Inconsistent node:fs import style.

realpathSync is statically imported at the top level (line 4), while readFileSync is dynamically imported inside loadSkills (line 23). Consider importing both statically for consistency, since the module is already paying the cost of importing node:fs at load time.

♻️ Suggested consolidation
-import { realpathSync } from 'node:fs';
+import { realpathSync, readFileSync } from 'node:fs';
+import { join, dirname } from 'node:path';

Then in loadSkills:

 async function loadSkills(): Promise<SkillEntry[]> {
-  const { readFileSync } = await import('node:fs');
-  const { join, dirname } = await import('node:path');
-
-  const pkgDir = dirname(fileURLToPath(import.meta.url));

Also applies to: 22-24


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

Open in Devin Review

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@packages/mcp/src/index.ts`:
- Around line 218-220: The comparison using realpathSync(process.argv[1]) can
throw when process.argv[1] is undefined or points to a non-existent path; wrap
the resolution in a try/catch and treat failures as non-equal so import as a
library does not crash. Specifically, in the block that defines resolvedArgv and
resolvedModule (using realpathSync, process.argv, fileURLToPath,
import.meta.url), catch errors from realpathSync and set resolvedArgv to a safe
fallback (e.g., undefined or an empty string) so the subsequent if (resolvedArgv
=== resolvedModule) check simply evaluates false instead of throwing; ensure you
do not change the semantics when argv is valid.
🧹 Nitpick comments (2)
packages/mcp/package.json (1)

22-22: Cross-platform compatibility: mkdir -p and cp are POSIX-only.

The prebuild script uses shell commands that won't work natively on Windows (cmd.exe). If Windows developer support matters, consider using a cross-platform alternative like cpy-cli or a small Node script. If the team is Unix-only, this is fine to leave as-is.

packages/mcp/src/index.ts (1)

4-4: Note: realpathSync is imported at the top level but also dynamically imported inside loadSkills (Line 23).

Minor inconsistency — readFileSync is dynamically imported in loadSkills while realpathSync from the same node:fs module is statically imported here. Not blocking, but worth being aware of.

- Wrap in try/catch so library imports don't crash
- Check process.argv[1] exists before calling realpathSync
- Also resolve import.meta.url with realpathSync for pnpm/hoisted setups
@rohitg00 rohitg00 merged commit 9930096 into main Feb 10, 2026
10 checks passed
@rohitg00 rohitg00 deleted the fix/mcp-server-symlink-startup branch February 10, 2026 11:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MCP server fails to start via npx: isMain guard broken by symlink resolution

1 participant