Skip to content

External MCP: Claude Desktop extension export and lock-safe writes - #1596

Draft
Salomon-Mazatlan wants to merge 30 commits into
ccbogel:masterfrom
Salomon-Mazatlan:cosas-de-mcp-20260921
Draft

Salomon-Mazatlan wants to merge 30 commits into
ccbogel:masterfrom
Salomon-Mazatlan:cosas-de-mcp-20260921

Conversation

@Salomon-Mazatlan

Copy link
Copy Markdown
Contributor

Hi @kaixxx, I have been testing the MCP connection you added in the latest update. I was asked to adapt it to a desktop application such as Claude Desktop, so I made some adjustments on top of your work. So far I have only tested it with Claude Desktop. I would like to hear your opinion before proposing it as a PR.

Button and installation file

  • New "Claude Desktop extension..." button (the name is provisional) in Settings, next to the external MCP access checkbox. It generates QualCoder.mcpb, which installs in Claude Desktop.
  • The file takes the port configured in QualCoder and keeps it editable from the extension settings.
image

Bridge inside the extension (version 1.0.2)

  • It connects Claude Desktop to the same local HTTP server that Claude Code and Codex already use. Nothing is replaced, it adds a second way in.
  • It renames the tools that contain a slash, because Claude does not accept that character, and maps them back when they are called.
  • It adds two tools to list and read resources, because Claude Desktop does not read resources on its own.
  • It answers even when QualCoder is closed, using the stored catalog and a message explaining what to check. Once QualCoder is opened it works without restarting Claude.
  • It logs every call received and how long it took.
  • Nothing needs to be installed, it uses the Node runtime that ships with Claude Desktop.
image

Execution of external requests

  • External operations moved from the GUI thread to a dedicated worker thread, one at a time, the same way the internal agent already works. With the GUI busy, every external write froze QualCoder for 5 seconds and then failed. In my tests it went from 9 of 40 writes in 90 seconds to 40 of 40 in under half a second, with no freezes.
  • Tool errors are returned to the client as a result with isError and a readable message, instead of a JSON-RPC error. The long SDK traceback no longer shows up in the log. Claude Code and Codex would see this change too.

Database

  • MCP writes no longer wait while holding the write lock. They try, and if the database is busy they release everything, wait a moment and retry, for up to 8 seconds. This way they cannot interrupt a QualCoder save. It also applies to the internal agent, which had the same risk.
  • A delete that finds the database busy no longer consumes its confirmation token.
  • In the same test case, the user's edit used to fail and the GUI connection was left with an open transaction. Now the edit is saved, the connection stays clean, and the external write goes through as soon as the window releases its read.

Quote matching

  • New search step that ignores line breaks, soft hyphens, words split at the end of a line, ligatures, typographic quotes and letter case. It does not depend on the AI engine and the internal agent benefits from it as well.
  • When a quote cannot be found, the message tells the agent how to fix it and reports whether approximate matching is unavailable.
image
@Salomon-Mazatlan Salomon-Mazatlan changed the title External MCP: Claude Desktop extension export, off-GUI-thread execution and lock-safe writes Sep 21, 2026
@kaixxx

kaixxx commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

Hi Lorenzo

Great that you have a chance to test the MCP access with Claude Desktop (and maybe Claude Code as well), as I can only test with Codex here.

It seems that the MCP-protocol has evolved since the version I was using, and that Claude Desktop is especially picky in some places (e.g., regarding tool naming conventions). But in order to make QualCoder as widely compatible as possible, we should fix some of the issues in QualCoder itself rather than only in the Claude Desktop bridge:

  • Rename all MCP tools containing slashes to full camel case, so codes_create_code instead of codes/create_code.
  • Provide qualcoder_list_resources and qualcoder_read_resource as regular server tools while retaining the native MCP resources. This would help every tool-oriented client, not only Claude Desktop.
  • Return expected tool failures like validation, permissions, database locks, missing objects, MCP tool results with isError: true. Unexpected internal errors should remain protocol/server errors.
  • Keep database retry and lock handling in QualCoder, because this affects internal and external agents equally.
  • The bridge should then mainly handle Claude Desktop’s MCPB packaging and the stdio-to-HTTP transport adaptation.

Other than that, a few comments

I would prefer not to add a Claude-specific export button to QualCoder. There are so many agentic frameworks out there; we cannot add a separate button for each. Could we instead build a generic, versioned QualCoder.mcpb as a release artifact and offer it through the QualCoder website and GitHub Releases? The default port can be included in the manifest and remain editable through the extension’s user_config. We could even consider submitting it to Claude Desktop’s extension directory later.

"External operations moved from the GUI thread to a dedicated worker thread..." -> This sounds like a very good idea.

The database-access optimizations: Also very good

Quote matching: As far as I understand, this does not add another MCP search tool but improves QualCoder’s internal quote matching, right? That's would be good, yes.

@kaixxx

kaixxx commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

Regarding the internal implementation of the bridge, here are some recommendations from Codex:

"

  • Use the official MCP SDK instead of manually implementing JSON-RPC, SSE parsing, initialization, and protocol negotiation.
  • Properly initialize the QualCoder HTTP server and send the negotiated MCP-Protocol-Version header on subsequent requests.
  • Forward cancellation and other lifecycle messages correctly.
  • Let QualCoder classify tool failures and return isError: true; the bridge should pass results through without reinterpreting every error.
  • Keep database locking, retries, permissions, and other business logic entirely inside QualCoder.
  • Avoid relying on a stored tool/resource catalog where possible. A cached catalog can provide a helpful offline message, but it may become outdated when the QualCoder version changes.
    "

BTW: I wonder if we could transform this into a small generic stdio <> http bridge that would be shipped with every QualCoder installation and could be invoked by qualcoder-mcp-stdio --url http://127.0.0.1:47363/mcp. This way, any MCP client that only supports stdio could use it. The QualCoder.mcpb could than become a very thin wrapper around that.

@Salomon-Mazatlan

Copy link
Copy Markdown
Contributor Author

Hi @kaixxx, I applied your observations.

In QualCoder:

  • The slashed tools were renamed with underscores (codes_create_code), in the same style as project_get_status. The server still accepts the old names, so existing Codex or Claude Code configurations keep working.
  • qualcoder_list_resources and qualcoder_read_resource are server tools; the native resources stay as they were. The catalog goes from 28 to 30 tools.
  • Classified errors. Validation, permissions, missing object, no open project and locked database come back as a result with isError. Unexpected internal errors remain server errors, and the SDK traceback no longer shows up in the log.
  • Retries and lock handling live in the server. Writes do not wait while holding the lock; they try, and if the database is busy they release everything and retry for up to 8 seconds. The message explaining a persistent lock is produced by the server, so the internal agent gets the same text as the external one.
  • External requests run on a dedicated worker thread, one at a time. No GUI freezes.
  • Quote matching tolerant of PDF layout (line breaks, soft hyphens, split words, ligatures, quote marks), with no new tools and no dependency on the AI engine.
  • New qualcoder/mcp_stdio.py, the generic stdio-to-HTTP bridge you proposed, built on the official Python SDK. Invoked with python -m qualcoder.mcp_stdio --port 47363 or qualcoder --mcp-stdio --port 47363; startup detects the flag before loading the GUI.

.mcpb

  • No button in QualCoder. It is built with tools/mcpb/build_mcpb.py as a release artifact, versioned with QualCoder, for GitHub Releases and the website. The default port is in the manifest and stays editable through user_config.
  • The bridge is written on the official MCP SDK and bundled with esbuild into one file (276 KB), so it only needs the Node runtime that ships with Claude Desktop. It does the stdio-to-HTTP transport only, passes results and errors through untouched, and cancellations are handled by the SDK.
  • The catalog snapshot is generated at build time, from the same QualCoder version, and is only shown while QualCoder is closed. Once QualCoder opens, the bridge reconnects and asks Claude Desktop to refresh the tool list.

what I did not do:

  • Making the .mcpb a wrapper around the Python bridge. That would require Python and QualCoder to be reachable from Claude Desktop, which is not the case with the Windows executable. The Node bridge on the SDK covers the same ground with equivalent behaviour.
@kaixxx

kaixxx commented Sep 22, 2026

Copy link
Copy Markdown
Collaborator

Hi Lorenzo,
thank you for implementing the suggestions, it looks very good.
I also agree with keeping the separate Node bridge in the .mcpb.

I have only a few remaining recommendations:

  • If we want to include qualcoder --mcp-stdio, we should make it a self-contained entry point. It should first check, using MCP initialization, whether a QualCoder server is already running. If so, it should attach without opening another GUI. Otherwise, it should launch the normal QualCoder application in a separate process and wait for its MCP endpoint. I think having this entry point would be a good idea. But if it is too complicated, we can also leave it for later.
  • If we go forward with this idea, a few things to consider:
    • Detect --mcp-stdio before importing PyQt and the rest of the GUI. Currently the check is at the bottom of main.py, so the GUI modules have already been loaded.
    • In mcp_stdio.py, only genuine connection/transport failures should be converted to “QualCoder is unreachable.” The broad except Exception could otherwise hide implementation errors.
    • On Windows, the packaged executable is currently built with console=False in the pyinstaller spec file, which removes stdin/stdout. To support MCP stdio reliably, we probably need console=True together with PyInstaller’s hide_console or minimize_console behaviour.
@kaixxx

kaixxx commented Sep 30, 2026

Copy link
Copy Markdown
Collaborator

Hi Lorenzo, I didn't realize that this is still a draft. I think we should include it into the final version 4.0 release. You've made very good improvements to the current MCP-setup, extended compatibility with Claude, and corrected some issues along the way. The ideas from my last comment can be left for the future. The PR seems good as it is.
Small disclaimer: I wasn't able to test your branch cosas-de-mcp-20260921 directly. I've tried cloning it, but don't get access for some reason.

@Salomon-Mazatlan

Copy link
Copy Markdown
Contributor Author

Hi Lorenzo, I didn't realize that this is still a draft. I think we should include it into the final version 4.0 release. You've made very good improvements to the current MCP-setup, extended compatibility with Claude, and corrected some issues along the way. The ideas from my last comment can be left for the future. The PR seems good as it is. Small disclaimer: I wasn't able to test your branch cosas-de-mcp-20260921 directly. I've tried cloning it, but don't get access for some reason.

Hi @kaixxx

I don't have access to my computer right now to work on this proposal. Would you mind making a PR with the adjustments from your fork? The GitHub app is only letting me leave comments.

@kaixxx

kaixxx commented Sep 30, 2026

Copy link
Copy Markdown
Collaborator

Would you mind making a PR with the adjustments from your fork?

Yes, of course. I'll see what I can do.

@Salomon-Mazatlan

Copy link
Copy Markdown
Contributor Author

Would you mind making a PR with the adjustments from your fork?

Yes, of course. I'll see what I can do.

Muchas gracias @kaixxx

This branch has not been deployed

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

Labels

None yet

2 participants