Skip to content

MCP server writes global KiCad library tables at startup and exits if it can't #5

Description

@barbecuesteve

Thanks for building this — the LCSC-to-KiCad conversion is just what I need.

One thing I noticed while evaluating it, in packages/mcp/src/index.ts:

async function main() {
  const registration = await ensureGlobalLibraryTables();
  if (!registration.success) {
    process.exit(1);
  }
  const httpPort = startHttpServer();
  ...
}

The server writes KiCad's global sym-lib-table and fp-lib-table before any tool is called. MCP hosts start servers speculatively — on session start, in every project, whether or not the user touches them. So merely having jlc-mcp in an MCP config mutates machine-global KiCad configuration that affects every project on the box, not just the one being worked on. For users with a deliberate library layout (shared repo-relative libraries, ${KIPRJMOD} paths) that's a surprising thing to have happen unasked.

The sharper problem is the process.exit(1). If the tables aren't writable, or the KiCad version isn't detected, the server doesn't start at all — so component_search, which is read-only and needs no libraries, becomes unavailable because of a filesystem write it never uses. A read path is gated behind an unrelated write.

Smaller version of the same thing: startHttpServer() binds a port unconditionally for the browser UI, so a user who only wants stdio tool calls gets a listening socket they didn't ask for.

Suggested fixes, roughly in order of value

  1. Make registration lazy — call ensureGlobalLibraryTables() on first library_* invocation rather than in main(). No new config surface, and search-only users never touch the tables.
  2. Degrade instead of exiting — on failure, log and disable the library_* tools, but keep serving component_search.
  3. Add a --read-only mode that omits the five writing tools from the advertised tool list entirely. That's a stronger guarantee than skipping startup work, since a model can't call a tool that isn't listed — useful for anyone wanting sourcing lookups without granting write access to their KiCad libraries.
  4. Same treatment for the HTTP server — --no-http, or start it lazily.

(1) and (2) alone would resolve it for me; (3) is the nice-to-have.

I'm happy to offer a PR for any subset of these if you'd welcome it. Just say which shape you'd prefer before I write anything, since the work spans packages/core and packages/mcp. Per your project protocol, I would include a changeset.

Unrelated: LICENSE file issue

package.json declares MIT, but there's no LICENSE in the repo, so GitHub reports the license as unset. Would you consider adding one? It makes contributing unambiguous.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions