Skip to content

Move ldk-server-mcp into the workspace - #188

Merged
benthecarman merged 6 commits into
lightningdevkit:mainfrom
tnull:2026-04-move-mcp-into-workspace
May 8, 2026
Merged

Move ldk-server-mcp into the workspace#188
benthecarman merged 6 commits into
lightningdevkit:mainfrom
tnull:2026-04-move-mcp-into-workspace

Conversation

@tnull

Copy link
Copy Markdown
Collaborator

Moving from https://github.com/tnull/ldk-server-mcp

Draft for now.

@tnull
tnull requested a review from benthecarmanApril 15, 2026 09:37
@ldk-reviews-bot

ldk-reviews-bot commented Apr 15, 2026

Copy link
Copy Markdown

🎉 This PR is now ready for review!
Please choose at least one reviewer by assigning them on the right bar.
If no reviewers are assigned within 10 minutes, I'll automatically assign one.
Once the first reviewer has submitted a review, a second will be assigned if required.

@tnull
tnull marked this pull request as draft April 15, 2026 09:37
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch 2 times, most recently from 70f8e5f to 3bc8a6eCompareApril 15, 2026 09:50

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Did a quick skim and ran through codex

Codex Review:

 - [P2] Honor storage.disk.dir_path when resolving credentials — /home/ben/projects/ldk-server/ldk-server-mcp/src/
config.rs:57-60
If the shared ldk-server config uses a custom storage.disk.dir_path, this parser drops that section entirely, so
resolve_config() can only look in ~/.ldk-server/... for api_key and tls.crt. In deployments that store node state
outside the default directory (a setup ldk-server-cli already supports), the MCP bridge will fail to authenticate
unless users also set both LDK_API_KEY and LDK_TLS_CERT_PATH by hand.
- [P2] Fall back to the default gRPC address when no base URL is configured — /home/ben/projects/ldk-server/ldk-
server-mcp/src/config.rs:112-116
In setups that rely on the standard 127.0.0.1:3536 gRPC address and only use the default credential files on disk,
this path exits with “Base URL not provided” instead of using the same default as ldk-server-cli. As a result, ldk-
server-mcp cannot start in the zero-config case unless users create a config file or export LDK_BASE_URL, even
though the server is running at the normal address.

I think these are two things we fixed in the cli since you created the MCP server.

Comment thread.github/workflows/mcp.yml Outdated
Comment thread.github/workflows/mcp.yml Outdated
Comment threade2e-tests/build.rs Outdated
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/README.md
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 3bc8a6e to 8d6d7b0CompareApril 16, 2026 09:47
@tnull
tnull requested a review from benthecarmanApril 16, 2026 09:47
@tnull
tnull marked this pull request as ready for review April 16, 2026 11:03

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

needs rebase too

Comment threadldk-server-mcp/src/config.rs
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/src/tools/mod.rs
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/src/main.rs
Comment threadldk-server-mcp/src/tools/mod.rs Outdated
Comment threadldk-server-mcp/src/tools/mod.rs Outdated
Comment threadldk-server-mcp/src/mcp.rs Outdated
Comment threadldk-server-mcp/src/main.rs Outdated
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch 2 times, most recently from b76ffeb to b0292ffCompareApril 23, 2026 13:37
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
// string, so we manually extract the string and turn it into bytes instead of delegating to the
// proto-typed deserializer.
pub async fn handle_sign_message(client: &LdkServerClient, args: Value) -> Result<Value, McpError> {
let message = args

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

any reason we aren't using the json decoder here? and in handle_verify_signature

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, see the comment above. Now introduced some extra {SignMessage,VerifySignature}Args structs deriving Deserialize to make this a bit cleaner. Let me know what you think.

- **Spec**: https://spec.modelcontextprotocol.io/
- **Transport**: stdio (one JSON-RPC 2.0 message per line)
- **Methods implemented**: `initialize`, `tools/list`, `tools/call`
- **Notifications handled**: `notifications/initialized` (ignored, no response)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't see us handling this anywhere, looks like we'd return METHOD_NOT_FOUND

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

No, we just skip in main:

// Notifications have no id — do not respondif request.id.is_none(){continue;}

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from b0292ff to 9295c38CompareApril 27, 2026 13:41
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- name: Get the current date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- name: Get the current date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 9295c38 to 9d74698CompareApril 27, 2026 13:44
@benthecarman

Copy link
Copy Markdown
Collaborator

Can you squash?

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 9d74698 to 0ff77b7CompareMay 5, 2026 09:05
@tnull

tnull commented May 5, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Can you squash?

Squashed without further changes.

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

final thing and then i think this is good

Comment on lines +120 to +121
if request.expiry_secs == 0 {
request.expiry_secs = DEFAULT_EXPIRY_SECS;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we'll need to do similar logic for DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, DEFAULT_MAX_PATH_COUNT, and DEFAULT_MAX_CHANNEL_SATURATION_POWER_OF_HALF where relevant

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from acfab96 to e729511CompareMay 6, 2026 12:29

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm on squash!

Image

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from e729511 to 429b1a7CompareMay 7, 2026 07:51
@tnull

tnull commented May 7, 2026

Copy link
Copy Markdown
CollaboratorAuthor

lgtm on squash!

Squashed without further changes.

@benthecarman

Copy link
Copy Markdown
Collaborator

the proto ci is failing now?

tnull added 2 commits May 8, 2026 14:17
Derive `serde::Deserialize` (alongside the existing `serde::Serialize`)
and `#[serde(default)]` on all generated prost messages so that JSON
payloads can be deserialized directly into the request types. This
reinstates the deserializers that were dropped in 8af3189 so that
clients like `ldk-server-mcp` can parse tool arguments straight into the
typed proto structs instead of threading every field through
`serde_json::Value`.
Generated with the assistance of AI (Claude).
Move the MCP bridge into the ldk-server workspace and switch it to an in-tree client dependency so workspace builds and tests cover it directly.
Co-Authored-By: HAL 9000
tnull added 4 commits May 8, 2026 14:17
Use the workspace-built MCP binary directly in tests so regressions are
caught without requiring a live server and without recompiling from
inside each test.
Generated with the assistance of AI (Claude).
Build the MCP binary in the e2e harness and exercise its stdio protocol against a live ldk-server so basic MCP functionality is verified without involving an agent.
Co-Authored-By: HAL 9000
Run MCP-specific formatting, clippy, and crate tests in a dedicated workflow and add a separate job that exercises the MCP e2e sanity suite on Ubuntu.
Co-Authored-By: HAL 9000
Describe the MCP bridge as a first-class workspace member and document how to build, test, and sanity-check it alongside the rest of ldk-server.
Co-Authored-By: HAL 9000
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 429b1a7 to 540bd3cCompareMay 8, 2026 12:19
@tnull

tnull commented May 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

the proto ci is failing now?

Ah, silent merge conflict it seems. Rebased.

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

amazing!

@benthecarman
benthecarman merged commit 388ff9e into lightningdevkit:mainMay 8, 2026
11 checks passed
Sign up for freeto 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.

4 participants

@tnull@ldk-reviews-bot@benthecarman@github-advanced-security
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Move `ldk-server-mcp` into the workspace by tnull · Pull Request #188 · lightningdevkit/ldk-server · GitHub
Skip to content

Move ldk-server-mcp into the workspace - #188

Merged
benthecarman merged 6 commits into
lightningdevkit:mainfrom
tnull:2026-04-move-mcp-into-workspace
May 8, 2026
Merged

Move ldk-server-mcp into the workspace#188
benthecarman merged 6 commits into
lightningdevkit:mainfrom
tnull:2026-04-move-mcp-into-workspace

Conversation

@tnull

Copy link
Copy Markdown
Collaborator

Moving from https://github.com/tnull/ldk-server-mcp

Draft for now.

@tnull
tnull requested a review from benthecarmanApril 15, 2026 09:37
@ldk-reviews-bot

ldk-reviews-bot commented Apr 15, 2026

Copy link
Copy Markdown

🎉 This PR is now ready for review!
Please choose at least one reviewer by assigning them on the right bar.
If no reviewers are assigned within 10 minutes, I'll automatically assign one.
Once the first reviewer has submitted a review, a second will be assigned if required.

@tnull
tnull marked this pull request as draft April 15, 2026 09:37
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch 2 times, most recently from 70f8e5f to 3bc8a6eCompareApril 15, 2026 09:50

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Did a quick skim and ran through codex

Codex Review:

 - [P2] Honor storage.disk.dir_path when resolving credentials — /home/ben/projects/ldk-server/ldk-server-mcp/src/
config.rs:57-60
If the shared ldk-server config uses a custom storage.disk.dir_path, this parser drops that section entirely, so
resolve_config() can only look in ~/.ldk-server/... for api_key and tls.crt. In deployments that store node state
outside the default directory (a setup ldk-server-cli already supports), the MCP bridge will fail to authenticate
unless users also set both LDK_API_KEY and LDK_TLS_CERT_PATH by hand.
- [P2] Fall back to the default gRPC address when no base URL is configured — /home/ben/projects/ldk-server/ldk-
server-mcp/src/config.rs:112-116
In setups that rely on the standard 127.0.0.1:3536 gRPC address and only use the default credential files on disk,
this path exits with “Base URL not provided” instead of using the same default as ldk-server-cli. As a result, ldk-
server-mcp cannot start in the zero-config case unless users create a config file or export LDK_BASE_URL, even
though the server is running at the normal address.

I think these are two things we fixed in the cli since you created the MCP server.

Comment thread.github/workflows/mcp.yml Outdated
Comment thread.github/workflows/mcp.yml Outdated
Comment threade2e-tests/build.rs Outdated
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/README.md
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 3bc8a6e to 8d6d7b0CompareApril 16, 2026 09:47
@tnull
tnull requested a review from benthecarmanApril 16, 2026 09:47
@tnull
tnull marked this pull request as ready for review April 16, 2026 11:03

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

needs rebase too

Comment threadldk-server-mcp/src/config.rs
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/src/tools/mod.rs
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/src/main.rs
Comment threadldk-server-mcp/src/tools/mod.rs Outdated
Comment threadldk-server-mcp/src/tools/mod.rs Outdated
Comment threadldk-server-mcp/src/mcp.rs Outdated
Comment threadldk-server-mcp/src/main.rs Outdated
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch 2 times, most recently from b76ffeb to b0292ffCompareApril 23, 2026 13:37
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
// string, so we manually extract the string and turn it into bytes instead of delegating to the
// proto-typed deserializer.
pub async fn handle_sign_message(client: &LdkServerClient, args: Value) -> Result<Value, McpError> {
let message = args

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

any reason we aren't using the json decoder here? and in handle_verify_signature

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, see the comment above. Now introduced some extra {SignMessage,VerifySignature}Args structs deriving Deserialize to make this a bit cleaner. Let me know what you think.

- **Spec**: https://spec.modelcontextprotocol.io/
- **Transport**: stdio (one JSON-RPC 2.0 message per line)
- **Methods implemented**: `initialize`, `tools/list`, `tools/call`
- **Notifications handled**: `notifications/initialized` (ignored, no response)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't see us handling this anywhere, looks like we'd return METHOD_NOT_FOUND

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

No, we just skip in main:

// Notifications have no id — do not respondif request.id.is_none(){continue;}

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from b0292ff to 9295c38CompareApril 27, 2026 13:41
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- name: Get the current date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- name: Get the current date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 9295c38 to 9d74698CompareApril 27, 2026 13:44
@benthecarman

Copy link
Copy Markdown
Collaborator

Can you squash?

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 9d74698 to 0ff77b7CompareMay 5, 2026 09:05
@tnull

tnull commented May 5, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Can you squash?

Squashed without further changes.

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

final thing and then i think this is good

Comment on lines +120 to +121
if request.expiry_secs == 0 {
request.expiry_secs = DEFAULT_EXPIRY_SECS;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we'll need to do similar logic for DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, DEFAULT_MAX_PATH_COUNT, and DEFAULT_MAX_CHANNEL_SATURATION_POWER_OF_HALF where relevant

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from acfab96 to e729511CompareMay 6, 2026 12:29

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm on squash!

Image

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from e729511 to 429b1a7CompareMay 7, 2026 07:51
@tnull

tnull commented May 7, 2026

Copy link
Copy Markdown
CollaboratorAuthor

lgtm on squash!

Squashed without further changes.

@benthecarman

Copy link
Copy Markdown
Collaborator

the proto ci is failing now?

tnull added 2 commits May 8, 2026 14:17
Derive `serde::Deserialize` (alongside the existing `serde::Serialize`)
and `#[serde(default)]` on all generated prost messages so that JSON
payloads can be deserialized directly into the request types. This
reinstates the deserializers that were dropped in 8af3189 so that
clients like `ldk-server-mcp` can parse tool arguments straight into the
typed proto structs instead of threading every field through
`serde_json::Value`.
Generated with the assistance of AI (Claude).
Move the MCP bridge into the ldk-server workspace and switch it to an in-tree client dependency so workspace builds and tests cover it directly.
Co-Authored-By: HAL 9000
tnull added 4 commits May 8, 2026 14:17
Use the workspace-built MCP binary directly in tests so regressions are
caught without requiring a live server and without recompiling from
inside each test.
Generated with the assistance of AI (Claude).
Build the MCP binary in the e2e harness and exercise its stdio protocol against a live ldk-server so basic MCP functionality is verified without involving an agent.
Co-Authored-By: HAL 9000
Run MCP-specific formatting, clippy, and crate tests in a dedicated workflow and add a separate job that exercises the MCP e2e sanity suite on Ubuntu.
Co-Authored-By: HAL 9000
Describe the MCP bridge as a first-class workspace member and document how to build, test, and sanity-check it alongside the rest of ldk-server.
Co-Authored-By: HAL 9000
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 429b1a7 to 540bd3cCompareMay 8, 2026 12:19
@tnull

tnull commented May 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

the proto ci is failing now?

Ah, silent merge conflict it seems. Rebased.

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

amazing!

@benthecarman
benthecarman merged commit 388ff9e into lightningdevkit:mainMay 8, 2026
11 checks passed
Sign up for freeto 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.

4 participants

@tnull@ldk-reviews-bot@benthecarman@github-advanced-security
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Move `ldk-server-mcp` into the workspace by tnull · Pull Request #188 · lightningdevkit/ldk-server · GitHub
Skip to content

Move ldk-server-mcp into the workspace - #188

Merged
benthecarman merged 6 commits into
lightningdevkit:mainfrom
tnull:2026-04-move-mcp-into-workspace
May 8, 2026
Merged

Move ldk-server-mcp into the workspace#188
benthecarman merged 6 commits into
lightningdevkit:mainfrom
tnull:2026-04-move-mcp-into-workspace

Conversation

@tnull

Copy link
Copy Markdown
Collaborator

Moving from https://github.com/tnull/ldk-server-mcp

Draft for now.

@tnull
tnull requested a review from benthecarmanApril 15, 2026 09:37
@ldk-reviews-bot

ldk-reviews-bot commented Apr 15, 2026

Copy link
Copy Markdown

🎉 This PR is now ready for review!
Please choose at least one reviewer by assigning them on the right bar.
If no reviewers are assigned within 10 minutes, I'll automatically assign one.
Once the first reviewer has submitted a review, a second will be assigned if required.

@tnull
tnull marked this pull request as draft April 15, 2026 09:37
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch 2 times, most recently from 70f8e5f to 3bc8a6eCompareApril 15, 2026 09:50

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Did a quick skim and ran through codex

Codex Review:

 - [P2] Honor storage.disk.dir_path when resolving credentials — /home/ben/projects/ldk-server/ldk-server-mcp/src/
config.rs:57-60
If the shared ldk-server config uses a custom storage.disk.dir_path, this parser drops that section entirely, so
resolve_config() can only look in ~/.ldk-server/... for api_key and tls.crt. In deployments that store node state
outside the default directory (a setup ldk-server-cli already supports), the MCP bridge will fail to authenticate
unless users also set both LDK_API_KEY and LDK_TLS_CERT_PATH by hand.
- [P2] Fall back to the default gRPC address when no base URL is configured — /home/ben/projects/ldk-server/ldk-
server-mcp/src/config.rs:112-116
In setups that rely on the standard 127.0.0.1:3536 gRPC address and only use the default credential files on disk,
this path exits with “Base URL not provided” instead of using the same default as ldk-server-cli. As a result, ldk-
server-mcp cannot start in the zero-config case unless users create a config file or export LDK_BASE_URL, even
though the server is running at the normal address.

I think these are two things we fixed in the cli since you created the MCP server.

Comment thread.github/workflows/mcp.yml Outdated
Comment thread.github/workflows/mcp.yml Outdated
Comment threade2e-tests/build.rs Outdated
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/README.md
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 3bc8a6e to 8d6d7b0CompareApril 16, 2026 09:47
@tnull
tnull requested a review from benthecarmanApril 16, 2026 09:47
@tnull
tnull marked this pull request as ready for review April 16, 2026 11:03

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

needs rebase too

Comment threadldk-server-mcp/src/config.rs
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/src/tools/mod.rs
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/src/main.rs
Comment threadldk-server-mcp/src/tools/mod.rs Outdated
Comment threadldk-server-mcp/src/tools/mod.rs Outdated
Comment threadldk-server-mcp/src/mcp.rs Outdated
Comment threadldk-server-mcp/src/main.rs Outdated
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch 2 times, most recently from b76ffeb to b0292ffCompareApril 23, 2026 13:37
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
// string, so we manually extract the string and turn it into bytes instead of delegating to the
// proto-typed deserializer.
pub async fn handle_sign_message(client: &LdkServerClient, args: Value) -> Result<Value, McpError> {
let message = args

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

any reason we aren't using the json decoder here? and in handle_verify_signature

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, see the comment above. Now introduced some extra {SignMessage,VerifySignature}Args structs deriving Deserialize to make this a bit cleaner. Let me know what you think.

- **Spec**: https://spec.modelcontextprotocol.io/
- **Transport**: stdio (one JSON-RPC 2.0 message per line)
- **Methods implemented**: `initialize`, `tools/list`, `tools/call`
- **Notifications handled**: `notifications/initialized` (ignored, no response)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't see us handling this anywhere, looks like we'd return METHOD_NOT_FOUND

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

No, we just skip in main:

// Notifications have no id — do not respondif request.id.is_none(){continue;}

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from b0292ff to 9295c38CompareApril 27, 2026 13:41
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- name: Get the current date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- name: Get the current date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 9295c38 to 9d74698CompareApril 27, 2026 13:44
@benthecarman

Copy link
Copy Markdown
Collaborator

Can you squash?

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 9d74698 to 0ff77b7CompareMay 5, 2026 09:05
@tnull

tnull commented May 5, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Can you squash?

Squashed without further changes.

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

final thing and then i think this is good

Comment on lines +120 to +121
if request.expiry_secs == 0 {
request.expiry_secs = DEFAULT_EXPIRY_SECS;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we'll need to do similar logic for DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, DEFAULT_MAX_PATH_COUNT, and DEFAULT_MAX_CHANNEL_SATURATION_POWER_OF_HALF where relevant

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from acfab96 to e729511CompareMay 6, 2026 12:29

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm on squash!

Image

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from e729511 to 429b1a7CompareMay 7, 2026 07:51
@tnull

tnull commented May 7, 2026

Copy link
Copy Markdown
CollaboratorAuthor

lgtm on squash!

Squashed without further changes.

@benthecarman

Copy link
Copy Markdown
Collaborator

the proto ci is failing now?

tnull added 2 commits May 8, 2026 14:17
Derive `serde::Deserialize` (alongside the existing `serde::Serialize`)
and `#[serde(default)]` on all generated prost messages so that JSON
payloads can be deserialized directly into the request types. This
reinstates the deserializers that were dropped in 8af3189 so that
clients like `ldk-server-mcp` can parse tool arguments straight into the
typed proto structs instead of threading every field through
`serde_json::Value`.
Generated with the assistance of AI (Claude).
Move the MCP bridge into the ldk-server workspace and switch it to an in-tree client dependency so workspace builds and tests cover it directly.
Co-Authored-By: HAL 9000
tnull added 4 commits May 8, 2026 14:17
Use the workspace-built MCP binary directly in tests so regressions are
caught without requiring a live server and without recompiling from
inside each test.
Generated with the assistance of AI (Claude).
Build the MCP binary in the e2e harness and exercise its stdio protocol against a live ldk-server so basic MCP functionality is verified without involving an agent.
Co-Authored-By: HAL 9000
Run MCP-specific formatting, clippy, and crate tests in a dedicated workflow and add a separate job that exercises the MCP e2e sanity suite on Ubuntu.
Co-Authored-By: HAL 9000
Describe the MCP bridge as a first-class workspace member and document how to build, test, and sanity-check it alongside the rest of ldk-server.
Co-Authored-By: HAL 9000
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 429b1a7 to 540bd3cCompareMay 8, 2026 12:19
@tnull

tnull commented May 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

the proto ci is failing now?

Ah, silent merge conflict it seems. Rebased.

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

amazing!

@benthecarman
benthecarman merged commit 388ff9e into lightningdevkit:mainMay 8, 2026
11 checks passed
Sign up for freeto 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.

4 participants

@tnull@ldk-reviews-bot@benthecarman@github-advanced-security
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Move `ldk-server-mcp` into the workspace by tnull · Pull Request #188 · lightningdevkit/ldk-server · GitHub
Skip to content

Move ldk-server-mcp into the workspace - #188

Merged
benthecarman merged 6 commits into
lightningdevkit:mainfrom
tnull:2026-04-move-mcp-into-workspace
May 8, 2026
Merged

Move ldk-server-mcp into the workspace#188
benthecarman merged 6 commits into
lightningdevkit:mainfrom
tnull:2026-04-move-mcp-into-workspace

Conversation

@tnull

Copy link
Copy Markdown
Collaborator

Moving from https://github.com/tnull/ldk-server-mcp

Draft for now.

@tnull
tnull requested a review from benthecarmanApril 15, 2026 09:37
@ldk-reviews-bot

ldk-reviews-bot commented Apr 15, 2026

Copy link
Copy Markdown

🎉 This PR is now ready for review!
Please choose at least one reviewer by assigning them on the right bar.
If no reviewers are assigned within 10 minutes, I'll automatically assign one.
Once the first reviewer has submitted a review, a second will be assigned if required.

@tnull
tnull marked this pull request as draft April 15, 2026 09:37
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch 2 times, most recently from 70f8e5f to 3bc8a6eCompareApril 15, 2026 09:50

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Did a quick skim and ran through codex

Codex Review:

 - [P2] Honor storage.disk.dir_path when resolving credentials — /home/ben/projects/ldk-server/ldk-server-mcp/src/
config.rs:57-60
If the shared ldk-server config uses a custom storage.disk.dir_path, this parser drops that section entirely, so
resolve_config() can only look in ~/.ldk-server/... for api_key and tls.crt. In deployments that store node state
outside the default directory (a setup ldk-server-cli already supports), the MCP bridge will fail to authenticate
unless users also set both LDK_API_KEY and LDK_TLS_CERT_PATH by hand.
- [P2] Fall back to the default gRPC address when no base URL is configured — /home/ben/projects/ldk-server/ldk-
server-mcp/src/config.rs:112-116
In setups that rely on the standard 127.0.0.1:3536 gRPC address and only use the default credential files on disk,
this path exits with “Base URL not provided” instead of using the same default as ldk-server-cli. As a result, ldk-
server-mcp cannot start in the zero-config case unless users create a config file or export LDK_BASE_URL, even
though the server is running at the normal address.

I think these are two things we fixed in the cli since you created the MCP server.

Comment thread.github/workflows/mcp.yml Outdated
Comment thread.github/workflows/mcp.yml Outdated
Comment threade2e-tests/build.rs Outdated
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/README.md
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 3bc8a6e to 8d6d7b0CompareApril 16, 2026 09:47
@tnull
tnull requested a review from benthecarmanApril 16, 2026 09:47
@tnull
tnull marked this pull request as ready for review April 16, 2026 11:03

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

needs rebase too

Comment threadldk-server-mcp/src/config.rs
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/src/tools/mod.rs
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/src/main.rs
Comment threadldk-server-mcp/src/tools/mod.rs Outdated
Comment threadldk-server-mcp/src/tools/mod.rs Outdated
Comment threadldk-server-mcp/src/mcp.rs Outdated
Comment threadldk-server-mcp/src/main.rs Outdated
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch 2 times, most recently from b76ffeb to b0292ffCompareApril 23, 2026 13:37
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
// string, so we manually extract the string and turn it into bytes instead of delegating to the
// proto-typed deserializer.
pub async fn handle_sign_message(client: &LdkServerClient, args: Value) -> Result<Value, McpError> {
let message = args

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

any reason we aren't using the json decoder here? and in handle_verify_signature

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, see the comment above. Now introduced some extra {SignMessage,VerifySignature}Args structs deriving Deserialize to make this a bit cleaner. Let me know what you think.

- **Spec**: https://spec.modelcontextprotocol.io/
- **Transport**: stdio (one JSON-RPC 2.0 message per line)
- **Methods implemented**: `initialize`, `tools/list`, `tools/call`
- **Notifications handled**: `notifications/initialized` (ignored, no response)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't see us handling this anywhere, looks like we'd return METHOD_NOT_FOUND

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

No, we just skip in main:

// Notifications have no id — do not respondif request.id.is_none(){continue;}

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from b0292ff to 9295c38CompareApril 27, 2026 13:41
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- name: Get the current date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- name: Get the current date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 9295c38 to 9d74698CompareApril 27, 2026 13:44
@benthecarman

Copy link
Copy Markdown
Collaborator

Can you squash?

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 9d74698 to 0ff77b7CompareMay 5, 2026 09:05
@tnull

tnull commented May 5, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Can you squash?

Squashed without further changes.

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

final thing and then i think this is good

Comment on lines +120 to +121
if request.expiry_secs == 0 {
request.expiry_secs = DEFAULT_EXPIRY_SECS;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we'll need to do similar logic for DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, DEFAULT_MAX_PATH_COUNT, and DEFAULT_MAX_CHANNEL_SATURATION_POWER_OF_HALF where relevant

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from acfab96 to e729511CompareMay 6, 2026 12:29

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm on squash!

Image

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from e729511 to 429b1a7CompareMay 7, 2026 07:51
@tnull

tnull commented May 7, 2026

Copy link
Copy Markdown
CollaboratorAuthor

lgtm on squash!

Squashed without further changes.

@benthecarman

Copy link
Copy Markdown
Collaborator

the proto ci is failing now?

tnull added 2 commits May 8, 2026 14:17
Derive `serde::Deserialize` (alongside the existing `serde::Serialize`)
and `#[serde(default)]` on all generated prost messages so that JSON
payloads can be deserialized directly into the request types. This
reinstates the deserializers that were dropped in 8af3189 so that
clients like `ldk-server-mcp` can parse tool arguments straight into the
typed proto structs instead of threading every field through
`serde_json::Value`.
Generated with the assistance of AI (Claude).
Move the MCP bridge into the ldk-server workspace and switch it to an in-tree client dependency so workspace builds and tests cover it directly.
Co-Authored-By: HAL 9000
tnull added 4 commits May 8, 2026 14:17
Use the workspace-built MCP binary directly in tests so regressions are
caught without requiring a live server and without recompiling from
inside each test.
Generated with the assistance of AI (Claude).
Build the MCP binary in the e2e harness and exercise its stdio protocol against a live ldk-server so basic MCP functionality is verified without involving an agent.
Co-Authored-By: HAL 9000
Run MCP-specific formatting, clippy, and crate tests in a dedicated workflow and add a separate job that exercises the MCP e2e sanity suite on Ubuntu.
Co-Authored-By: HAL 9000
Describe the MCP bridge as a first-class workspace member and document how to build, test, and sanity-check it alongside the rest of ldk-server.
Co-Authored-By: HAL 9000
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 429b1a7 to 540bd3cCompareMay 8, 2026 12:19
@tnull

tnull commented May 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

the proto ci is failing now?

Ah, silent merge conflict it seems. Rebased.

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

amazing!

@benthecarman
benthecarman merged commit 388ff9e into lightningdevkit:mainMay 8, 2026
11 checks passed
Sign up for freeto 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.

4 participants

@tnull@ldk-reviews-bot@benthecarman@github-advanced-security
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Move `ldk-server-mcp` into the workspace by tnull · Pull Request #188 · lightningdevkit/ldk-server · GitHub
Skip to content

Move ldk-server-mcp into the workspace - #188

Merged
benthecarman merged 6 commits into
lightningdevkit:mainfrom
tnull:2026-04-move-mcp-into-workspace
May 8, 2026
Merged

Move ldk-server-mcp into the workspace#188
benthecarman merged 6 commits into
lightningdevkit:mainfrom
tnull:2026-04-move-mcp-into-workspace

Conversation

@tnull

Copy link
Copy Markdown
Collaborator

Moving from https://github.com/tnull/ldk-server-mcp

Draft for now.

@tnull
tnull requested a review from benthecarmanApril 15, 2026 09:37
@ldk-reviews-bot

ldk-reviews-bot commented Apr 15, 2026

Copy link
Copy Markdown

🎉 This PR is now ready for review!
Please choose at least one reviewer by assigning them on the right bar.
If no reviewers are assigned within 10 minutes, I'll automatically assign one.
Once the first reviewer has submitted a review, a second will be assigned if required.

@tnull
tnull marked this pull request as draft April 15, 2026 09:37
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch 2 times, most recently from 70f8e5f to 3bc8a6eCompareApril 15, 2026 09:50

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Did a quick skim and ran through codex

Codex Review:

 - [P2] Honor storage.disk.dir_path when resolving credentials — /home/ben/projects/ldk-server/ldk-server-mcp/src/
config.rs:57-60
If the shared ldk-server config uses a custom storage.disk.dir_path, this parser drops that section entirely, so
resolve_config() can only look in ~/.ldk-server/... for api_key and tls.crt. In deployments that store node state
outside the default directory (a setup ldk-server-cli already supports), the MCP bridge will fail to authenticate
unless users also set both LDK_API_KEY and LDK_TLS_CERT_PATH by hand.
- [P2] Fall back to the default gRPC address when no base URL is configured — /home/ben/projects/ldk-server/ldk-
server-mcp/src/config.rs:112-116
In setups that rely on the standard 127.0.0.1:3536 gRPC address and only use the default credential files on disk,
this path exits with “Base URL not provided” instead of using the same default as ldk-server-cli. As a result, ldk-
server-mcp cannot start in the zero-config case unless users create a config file or export LDK_BASE_URL, even
though the server is running at the normal address.

I think these are two things we fixed in the cli since you created the MCP server.

Comment thread.github/workflows/mcp.yml Outdated
Comment thread.github/workflows/mcp.yml Outdated
Comment threade2e-tests/build.rs Outdated
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/README.md
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 3bc8a6e to 8d6d7b0CompareApril 16, 2026 09:47
@tnull
tnull requested a review from benthecarmanApril 16, 2026 09:47
@tnull
tnull marked this pull request as ready for review April 16, 2026 11:03

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

needs rebase too

Comment threadldk-server-mcp/src/config.rs
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/src/tools/mod.rs
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/src/main.rs
Comment threadldk-server-mcp/src/tools/mod.rs Outdated
Comment threadldk-server-mcp/src/tools/mod.rs Outdated
Comment threadldk-server-mcp/src/mcp.rs Outdated
Comment threadldk-server-mcp/src/main.rs Outdated
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch 2 times, most recently from b76ffeb to b0292ffCompareApril 23, 2026 13:37
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
// string, so we manually extract the string and turn it into bytes instead of delegating to the
// proto-typed deserializer.
pub async fn handle_sign_message(client: &LdkServerClient, args: Value) -> Result<Value, McpError> {
let message = args

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

any reason we aren't using the json decoder here? and in handle_verify_signature

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, see the comment above. Now introduced some extra {SignMessage,VerifySignature}Args structs deriving Deserialize to make this a bit cleaner. Let me know what you think.

- **Spec**: https://spec.modelcontextprotocol.io/
- **Transport**: stdio (one JSON-RPC 2.0 message per line)
- **Methods implemented**: `initialize`, `tools/list`, `tools/call`
- **Notifications handled**: `notifications/initialized` (ignored, no response)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't see us handling this anywhere, looks like we'd return METHOD_NOT_FOUND

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

No, we just skip in main:

// Notifications have no id — do not respondif request.id.is_none(){continue;}

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from b0292ff to 9295c38CompareApril 27, 2026 13:41
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- name: Get the current date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- name: Get the current date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 9295c38 to 9d74698CompareApril 27, 2026 13:44
@benthecarman

Copy link
Copy Markdown
Collaborator

Can you squash?

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 9d74698 to 0ff77b7CompareMay 5, 2026 09:05
@tnull

tnull commented May 5, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Can you squash?

Squashed without further changes.

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

final thing and then i think this is good

Comment on lines +120 to +121
if request.expiry_secs == 0 {
request.expiry_secs = DEFAULT_EXPIRY_SECS;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we'll need to do similar logic for DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, DEFAULT_MAX_PATH_COUNT, and DEFAULT_MAX_CHANNEL_SATURATION_POWER_OF_HALF where relevant

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from acfab96 to e729511CompareMay 6, 2026 12:29

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm on squash!

Image

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from e729511 to 429b1a7CompareMay 7, 2026 07:51
@tnull

tnull commented May 7, 2026

Copy link
Copy Markdown
CollaboratorAuthor

lgtm on squash!

Squashed without further changes.

@benthecarman

Copy link
Copy Markdown
Collaborator

the proto ci is failing now?

tnull added 2 commits May 8, 2026 14:17
Derive `serde::Deserialize` (alongside the existing `serde::Serialize`)
and `#[serde(default)]` on all generated prost messages so that JSON
payloads can be deserialized directly into the request types. This
reinstates the deserializers that were dropped in 8af3189 so that
clients like `ldk-server-mcp` can parse tool arguments straight into the
typed proto structs instead of threading every field through
`serde_json::Value`.
Generated with the assistance of AI (Claude).
Move the MCP bridge into the ldk-server workspace and switch it to an in-tree client dependency so workspace builds and tests cover it directly.
Co-Authored-By: HAL 9000
tnull added 4 commits May 8, 2026 14:17
Use the workspace-built MCP binary directly in tests so regressions are
caught without requiring a live server and without recompiling from
inside each test.
Generated with the assistance of AI (Claude).
Build the MCP binary in the e2e harness and exercise its stdio protocol against a live ldk-server so basic MCP functionality is verified without involving an agent.
Co-Authored-By: HAL 9000
Run MCP-specific formatting, clippy, and crate tests in a dedicated workflow and add a separate job that exercises the MCP e2e sanity suite on Ubuntu.
Co-Authored-By: HAL 9000
Describe the MCP bridge as a first-class workspace member and document how to build, test, and sanity-check it alongside the rest of ldk-server.
Co-Authored-By: HAL 9000
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 429b1a7 to 540bd3cCompareMay 8, 2026 12:19
@tnull

tnull commented May 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

the proto ci is failing now?

Ah, silent merge conflict it seems. Rebased.

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

amazing!

@benthecarman
benthecarman merged commit 388ff9e into lightningdevkit:mainMay 8, 2026
11 checks passed
Sign up for freeto 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.

4 participants

@tnull@ldk-reviews-bot@benthecarman@github-advanced-security
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Move `ldk-server-mcp` into the workspace by tnull · Pull Request #188 · lightningdevkit/ldk-server · GitHub
Skip to content

Move ldk-server-mcp into the workspace - #188

Merged
benthecarman merged 6 commits into
lightningdevkit:mainfrom
tnull:2026-04-move-mcp-into-workspace
May 8, 2026
Merged

Move ldk-server-mcp into the workspace#188
benthecarman merged 6 commits into
lightningdevkit:mainfrom
tnull:2026-04-move-mcp-into-workspace

Conversation

@tnull

Copy link
Copy Markdown
Collaborator

Moving from https://github.com/tnull/ldk-server-mcp

Draft for now.

@tnull
tnull requested a review from benthecarmanApril 15, 2026 09:37
@ldk-reviews-bot

ldk-reviews-bot commented Apr 15, 2026

Copy link
Copy Markdown

🎉 This PR is now ready for review!
Please choose at least one reviewer by assigning them on the right bar.
If no reviewers are assigned within 10 minutes, I'll automatically assign one.
Once the first reviewer has submitted a review, a second will be assigned if required.

@tnull
tnull marked this pull request as draft April 15, 2026 09:37
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch 2 times, most recently from 70f8e5f to 3bc8a6eCompareApril 15, 2026 09:50

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Did a quick skim and ran through codex

Codex Review:

 - [P2] Honor storage.disk.dir_path when resolving credentials — /home/ben/projects/ldk-server/ldk-server-mcp/src/
config.rs:57-60
If the shared ldk-server config uses a custom storage.disk.dir_path, this parser drops that section entirely, so
resolve_config() can only look in ~/.ldk-server/... for api_key and tls.crt. In deployments that store node state
outside the default directory (a setup ldk-server-cli already supports), the MCP bridge will fail to authenticate
unless users also set both LDK_API_KEY and LDK_TLS_CERT_PATH by hand.
- [P2] Fall back to the default gRPC address when no base URL is configured — /home/ben/projects/ldk-server/ldk-
server-mcp/src/config.rs:112-116
In setups that rely on the standard 127.0.0.1:3536 gRPC address and only use the default credential files on disk,
this path exits with “Base URL not provided” instead of using the same default as ldk-server-cli. As a result, ldk-
server-mcp cannot start in the zero-config case unless users create a config file or export LDK_BASE_URL, even
though the server is running at the normal address.

I think these are two things we fixed in the cli since you created the MCP server.

Comment thread.github/workflows/mcp.yml Outdated
Comment thread.github/workflows/mcp.yml Outdated
Comment threade2e-tests/build.rs Outdated
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/README.md
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 3bc8a6e to 8d6d7b0CompareApril 16, 2026 09:47
@tnull
tnull requested a review from benthecarmanApril 16, 2026 09:47
@tnull
tnull marked this pull request as ready for review April 16, 2026 11:03

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

needs rebase too

Comment threadldk-server-mcp/src/config.rs
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/src/tools/mod.rs
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/src/main.rs
Comment threadldk-server-mcp/src/tools/mod.rs Outdated
Comment threadldk-server-mcp/src/tools/mod.rs Outdated
Comment threadldk-server-mcp/src/mcp.rs Outdated
Comment threadldk-server-mcp/src/main.rs Outdated
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch 2 times, most recently from b76ffeb to b0292ffCompareApril 23, 2026 13:37
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
// string, so we manually extract the string and turn it into bytes instead of delegating to the
// proto-typed deserializer.
pub async fn handle_sign_message(client: &LdkServerClient, args: Value) -> Result<Value, McpError> {
let message = args

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

any reason we aren't using the json decoder here? and in handle_verify_signature

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, see the comment above. Now introduced some extra {SignMessage,VerifySignature}Args structs deriving Deserialize to make this a bit cleaner. Let me know what you think.

- **Spec**: https://spec.modelcontextprotocol.io/
- **Transport**: stdio (one JSON-RPC 2.0 message per line)
- **Methods implemented**: `initialize`, `tools/list`, `tools/call`
- **Notifications handled**: `notifications/initialized` (ignored, no response)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't see us handling this anywhere, looks like we'd return METHOD_NOT_FOUND

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

No, we just skip in main:

// Notifications have no id — do not respondif request.id.is_none(){continue;}

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from b0292ff to 9295c38CompareApril 27, 2026 13:41
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- name: Get the current date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- name: Get the current date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 9295c38 to 9d74698CompareApril 27, 2026 13:44
@benthecarman

Copy link
Copy Markdown
Collaborator

Can you squash?

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 9d74698 to 0ff77b7CompareMay 5, 2026 09:05
@tnull

tnull commented May 5, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Can you squash?

Squashed without further changes.

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

final thing and then i think this is good

Comment on lines +120 to +121
if request.expiry_secs == 0 {
request.expiry_secs = DEFAULT_EXPIRY_SECS;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we'll need to do similar logic for DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, DEFAULT_MAX_PATH_COUNT, and DEFAULT_MAX_CHANNEL_SATURATION_POWER_OF_HALF where relevant

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from acfab96 to e729511CompareMay 6, 2026 12:29

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm on squash!

Image

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from e729511 to 429b1a7CompareMay 7, 2026 07:51
@tnull

tnull commented May 7, 2026

Copy link
Copy Markdown
CollaboratorAuthor

lgtm on squash!

Squashed without further changes.

@benthecarman

Copy link
Copy Markdown
Collaborator

the proto ci is failing now?

tnull added 2 commits May 8, 2026 14:17
Derive `serde::Deserialize` (alongside the existing `serde::Serialize`)
and `#[serde(default)]` on all generated prost messages so that JSON
payloads can be deserialized directly into the request types. This
reinstates the deserializers that were dropped in 8af3189 so that
clients like `ldk-server-mcp` can parse tool arguments straight into the
typed proto structs instead of threading every field through
`serde_json::Value`.
Generated with the assistance of AI (Claude).
Move the MCP bridge into the ldk-server workspace and switch it to an in-tree client dependency so workspace builds and tests cover it directly.
Co-Authored-By: HAL 9000
tnull added 4 commits May 8, 2026 14:17
Use the workspace-built MCP binary directly in tests so regressions are
caught without requiring a live server and without recompiling from
inside each test.
Generated with the assistance of AI (Claude).
Build the MCP binary in the e2e harness and exercise its stdio protocol against a live ldk-server so basic MCP functionality is verified without involving an agent.
Co-Authored-By: HAL 9000
Run MCP-specific formatting, clippy, and crate tests in a dedicated workflow and add a separate job that exercises the MCP e2e sanity suite on Ubuntu.
Co-Authored-By: HAL 9000
Describe the MCP bridge as a first-class workspace member and document how to build, test, and sanity-check it alongside the rest of ldk-server.
Co-Authored-By: HAL 9000
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 429b1a7 to 540bd3cCompareMay 8, 2026 12:19
@tnull

tnull commented May 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

the proto ci is failing now?

Ah, silent merge conflict it seems. Rebased.

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

amazing!

@benthecarman
benthecarman merged commit 388ff9e into lightningdevkit:mainMay 8, 2026
11 checks passed
Sign up for freeto 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.

4 participants

@tnull@ldk-reviews-bot@benthecarman@github-advanced-security
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Move `ldk-server-mcp` into the workspace by tnull · Pull Request #188 · lightningdevkit/ldk-server · GitHub
Skip to content

Move ldk-server-mcp into the workspace - #188

Merged
benthecarman merged 6 commits into
lightningdevkit:mainfrom
tnull:2026-04-move-mcp-into-workspace
May 8, 2026
Merged

Move ldk-server-mcp into the workspace#188
benthecarman merged 6 commits into
lightningdevkit:mainfrom
tnull:2026-04-move-mcp-into-workspace

Conversation

@tnull

Copy link
Copy Markdown
Collaborator

Moving from https://github.com/tnull/ldk-server-mcp

Draft for now.

@tnull
tnull requested a review from benthecarmanApril 15, 2026 09:37
@ldk-reviews-bot

ldk-reviews-bot commented Apr 15, 2026

Copy link
Copy Markdown

🎉 This PR is now ready for review!
Please choose at least one reviewer by assigning them on the right bar.
If no reviewers are assigned within 10 minutes, I'll automatically assign one.
Once the first reviewer has submitted a review, a second will be assigned if required.

@tnull
tnull marked this pull request as draft April 15, 2026 09:37
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch 2 times, most recently from 70f8e5f to 3bc8a6eCompareApril 15, 2026 09:50

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Did a quick skim and ran through codex

Codex Review:

 - [P2] Honor storage.disk.dir_path when resolving credentials — /home/ben/projects/ldk-server/ldk-server-mcp/src/
config.rs:57-60
If the shared ldk-server config uses a custom storage.disk.dir_path, this parser drops that section entirely, so
resolve_config() can only look in ~/.ldk-server/... for api_key and tls.crt. In deployments that store node state
outside the default directory (a setup ldk-server-cli already supports), the MCP bridge will fail to authenticate
unless users also set both LDK_API_KEY and LDK_TLS_CERT_PATH by hand.
- [P2] Fall back to the default gRPC address when no base URL is configured — /home/ben/projects/ldk-server/ldk-
server-mcp/src/config.rs:112-116
In setups that rely on the standard 127.0.0.1:3536 gRPC address and only use the default credential files on disk,
this path exits with “Base URL not provided” instead of using the same default as ldk-server-cli. As a result, ldk-
server-mcp cannot start in the zero-config case unless users create a config file or export LDK_BASE_URL, even
though the server is running at the normal address.

I think these are two things we fixed in the cli since you created the MCP server.

Comment thread.github/workflows/mcp.yml Outdated
Comment thread.github/workflows/mcp.yml Outdated
Comment threade2e-tests/build.rs Outdated
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/README.md
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 3bc8a6e to 8d6d7b0CompareApril 16, 2026 09:47
@tnull
tnull requested a review from benthecarmanApril 16, 2026 09:47
@tnull
tnull marked this pull request as ready for review April 16, 2026 11:03

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

needs rebase too

Comment threadldk-server-mcp/src/config.rs
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/src/tools/mod.rs
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/src/main.rs
Comment threadldk-server-mcp/src/tools/mod.rs Outdated
Comment threadldk-server-mcp/src/tools/mod.rs Outdated
Comment threadldk-server-mcp/src/mcp.rs Outdated
Comment threadldk-server-mcp/src/main.rs Outdated
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch 2 times, most recently from b76ffeb to b0292ffCompareApril 23, 2026 13:37
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
// string, so we manually extract the string and turn it into bytes instead of delegating to the
// proto-typed deserializer.
pub async fn handle_sign_message(client: &LdkServerClient, args: Value) -> Result<Value, McpError> {
let message = args

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

any reason we aren't using the json decoder here? and in handle_verify_signature

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, see the comment above. Now introduced some extra {SignMessage,VerifySignature}Args structs deriving Deserialize to make this a bit cleaner. Let me know what you think.

- **Spec**: https://spec.modelcontextprotocol.io/
- **Transport**: stdio (one JSON-RPC 2.0 message per line)
- **Methods implemented**: `initialize`, `tools/list`, `tools/call`
- **Notifications handled**: `notifications/initialized` (ignored, no response)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't see us handling this anywhere, looks like we'd return METHOD_NOT_FOUND

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

No, we just skip in main:

// Notifications have no id — do not respondif request.id.is_none(){continue;}

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from b0292ff to 9295c38CompareApril 27, 2026 13:41
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- name: Get the current date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- name: Get the current date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 9295c38 to 9d74698CompareApril 27, 2026 13:44
@benthecarman

Copy link
Copy Markdown
Collaborator

Can you squash?

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 9d74698 to 0ff77b7CompareMay 5, 2026 09:05
@tnull

tnull commented May 5, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Can you squash?

Squashed without further changes.

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

final thing and then i think this is good

Comment on lines +120 to +121
if request.expiry_secs == 0 {
request.expiry_secs = DEFAULT_EXPIRY_SECS;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we'll need to do similar logic for DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, DEFAULT_MAX_PATH_COUNT, and DEFAULT_MAX_CHANNEL_SATURATION_POWER_OF_HALF where relevant

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from acfab96 to e729511CompareMay 6, 2026 12:29

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm on squash!

Image

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from e729511 to 429b1a7CompareMay 7, 2026 07:51
@tnull

tnull commented May 7, 2026

Copy link
Copy Markdown
CollaboratorAuthor

lgtm on squash!

Squashed without further changes.

@benthecarman

Copy link
Copy Markdown
Collaborator

the proto ci is failing now?

tnull added 2 commits May 8, 2026 14:17
Derive `serde::Deserialize` (alongside the existing `serde::Serialize`)
and `#[serde(default)]` on all generated prost messages so that JSON
payloads can be deserialized directly into the request types. This
reinstates the deserializers that were dropped in 8af3189 so that
clients like `ldk-server-mcp` can parse tool arguments straight into the
typed proto structs instead of threading every field through
`serde_json::Value`.
Generated with the assistance of AI (Claude).
Move the MCP bridge into the ldk-server workspace and switch it to an in-tree client dependency so workspace builds and tests cover it directly.
Co-Authored-By: HAL 9000
tnull added 4 commits May 8, 2026 14:17
Use the workspace-built MCP binary directly in tests so regressions are
caught without requiring a live server and without recompiling from
inside each test.
Generated with the assistance of AI (Claude).
Build the MCP binary in the e2e harness and exercise its stdio protocol against a live ldk-server so basic MCP functionality is verified without involving an agent.
Co-Authored-By: HAL 9000
Run MCP-specific formatting, clippy, and crate tests in a dedicated workflow and add a separate job that exercises the MCP e2e sanity suite on Ubuntu.
Co-Authored-By: HAL 9000
Describe the MCP bridge as a first-class workspace member and document how to build, test, and sanity-check it alongside the rest of ldk-server.
Co-Authored-By: HAL 9000
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 429b1a7 to 540bd3cCompareMay 8, 2026 12:19
@tnull

tnull commented May 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

the proto ci is failing now?

Ah, silent merge conflict it seems. Rebased.

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

amazing!

@benthecarman
benthecarman merged commit 388ff9e into lightningdevkit:mainMay 8, 2026
11 checks passed
Sign up for freeto 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.

4 participants

@tnull@ldk-reviews-bot@benthecarman@github-advanced-security
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Move `ldk-server-mcp` into the workspace by tnull · Pull Request #188 · lightningdevkit/ldk-server · GitHub
Skip to content

Move ldk-server-mcp into the workspace - #188

Merged
benthecarman merged 6 commits into
lightningdevkit:mainfrom
tnull:2026-04-move-mcp-into-workspace
May 8, 2026
Merged

Move ldk-server-mcp into the workspace#188
benthecarman merged 6 commits into
lightningdevkit:mainfrom
tnull:2026-04-move-mcp-into-workspace

Conversation

@tnull

Copy link
Copy Markdown
Collaborator

Moving from https://github.com/tnull/ldk-server-mcp

Draft for now.

@tnull
tnull requested a review from benthecarmanApril 15, 2026 09:37
@ldk-reviews-bot

ldk-reviews-bot commented Apr 15, 2026

Copy link
Copy Markdown

🎉 This PR is now ready for review!
Please choose at least one reviewer by assigning them on the right bar.
If no reviewers are assigned within 10 minutes, I'll automatically assign one.
Once the first reviewer has submitted a review, a second will be assigned if required.

@tnull
tnull marked this pull request as draft April 15, 2026 09:37
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch 2 times, most recently from 70f8e5f to 3bc8a6eCompareApril 15, 2026 09:50

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Did a quick skim and ran through codex

Codex Review:

 - [P2] Honor storage.disk.dir_path when resolving credentials — /home/ben/projects/ldk-server/ldk-server-mcp/src/
config.rs:57-60
If the shared ldk-server config uses a custom storage.disk.dir_path, this parser drops that section entirely, so
resolve_config() can only look in ~/.ldk-server/... for api_key and tls.crt. In deployments that store node state
outside the default directory (a setup ldk-server-cli already supports), the MCP bridge will fail to authenticate
unless users also set both LDK_API_KEY and LDK_TLS_CERT_PATH by hand.
- [P2] Fall back to the default gRPC address when no base URL is configured — /home/ben/projects/ldk-server/ldk-
server-mcp/src/config.rs:112-116
In setups that rely on the standard 127.0.0.1:3536 gRPC address and only use the default credential files on disk,
this path exits with “Base URL not provided” instead of using the same default as ldk-server-cli. As a result, ldk-
server-mcp cannot start in the zero-config case unless users create a config file or export LDK_BASE_URL, even
though the server is running at the normal address.

I think these are two things we fixed in the cli since you created the MCP server.

Comment thread.github/workflows/mcp.yml Outdated
Comment thread.github/workflows/mcp.yml Outdated
Comment threade2e-tests/build.rs Outdated
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/README.md
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 3bc8a6e to 8d6d7b0CompareApril 16, 2026 09:47
@tnull
tnull requested a review from benthecarmanApril 16, 2026 09:47
@tnull
tnull marked this pull request as ready for review April 16, 2026 11:03

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

needs rebase too

Comment threadldk-server-mcp/src/config.rs
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/src/tools/mod.rs
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
Comment threadldk-server-mcp/src/main.rs
Comment threadldk-server-mcp/src/tools/mod.rs Outdated
Comment threadldk-server-mcp/src/tools/mod.rs Outdated
Comment threadldk-server-mcp/src/mcp.rs Outdated
Comment threadldk-server-mcp/src/main.rs Outdated
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch 2 times, most recently from b76ffeb to b0292ffCompareApril 23, 2026 13:37
Comment threadldk-server-mcp/src/tools/handlers.rs Outdated
// string, so we manually extract the string and turn it into bytes instead of delegating to the
// proto-typed deserializer.
pub async fn handle_sign_message(client: &LdkServerClient, args: Value) -> Result<Value, McpError> {
let message = args

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

any reason we aren't using the json decoder here? and in handle_verify_signature

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Hmm, see the comment above. Now introduced some extra {SignMessage,VerifySignature}Args structs deriving Deserialize to make this a bit cleaner. Let me know what you think.

- **Spec**: https://spec.modelcontextprotocol.io/
- **Transport**: stdio (one JSON-RPC 2.0 message per line)
- **Methods implemented**: `initialize`, `tools/list`, `tools/call`
- **Notifications handled**: `notifications/initialized` (ignored, no response)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't see us handling this anywhere, looks like we'd return METHOD_NOT_FOUND

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

No, we just skip in main:

// Notifications have no id — do not respondif request.id.is_none(){continue;}

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from b0292ff to 9295c38CompareApril 27, 2026 13:41
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- name: Get the current date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@nightly
- name: Get the current date
run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v8
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 9295c38 to 9d74698CompareApril 27, 2026 13:44
@benthecarman

Copy link
Copy Markdown
Collaborator

Can you squash?

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 9d74698 to 0ff77b7CompareMay 5, 2026 09:05
@tnull

tnull commented May 5, 2026

Copy link
Copy Markdown
CollaboratorAuthor

Can you squash?

Squashed without further changes.

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

final thing and then i think this is good

Comment on lines +120 to +121
if request.expiry_secs == 0 {
request.expiry_secs = DEFAULT_EXPIRY_SECS;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we'll need to do similar logic for DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, DEFAULT_MAX_PATH_COUNT, and DEFAULT_MAX_CHANNEL_SATURATION_POWER_OF_HALF where relevant

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from acfab96 to e729511CompareMay 6, 2026 12:29

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

lgtm on squash!

Image

@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from e729511 to 429b1a7CompareMay 7, 2026 07:51
@tnull

tnull commented May 7, 2026

Copy link
Copy Markdown
CollaboratorAuthor

lgtm on squash!

Squashed without further changes.

@benthecarman

Copy link
Copy Markdown
Collaborator

the proto ci is failing now?

tnull added 2 commits May 8, 2026 14:17
Derive `serde::Deserialize` (alongside the existing `serde::Serialize`)
and `#[serde(default)]` on all generated prost messages so that JSON
payloads can be deserialized directly into the request types. This
reinstates the deserializers that were dropped in 8af3189 so that
clients like `ldk-server-mcp` can parse tool arguments straight into the
typed proto structs instead of threading every field through
`serde_json::Value`.
Generated with the assistance of AI (Claude).
Move the MCP bridge into the ldk-server workspace and switch it to an in-tree client dependency so workspace builds and tests cover it directly.
Co-Authored-By: HAL 9000
tnull added 4 commits May 8, 2026 14:17
Use the workspace-built MCP binary directly in tests so regressions are
caught without requiring a live server and without recompiling from
inside each test.
Generated with the assistance of AI (Claude).
Build the MCP binary in the e2e harness and exercise its stdio protocol against a live ldk-server so basic MCP functionality is verified without involving an agent.
Co-Authored-By: HAL 9000
Run MCP-specific formatting, clippy, and crate tests in a dedicated workflow and add a separate job that exercises the MCP e2e sanity suite on Ubuntu.
Co-Authored-By: HAL 9000
Describe the MCP bridge as a first-class workspace member and document how to build, test, and sanity-check it alongside the rest of ldk-server.
Co-Authored-By: HAL 9000
@tnull
tnullforce-pushed the 2026-04-move-mcp-into-workspace branch from 429b1a7 to 540bd3cCompareMay 8, 2026 12:19
@tnull

tnull commented May 8, 2026

Copy link
Copy Markdown
CollaboratorAuthor

the proto ci is failing now?

Ah, silent merge conflict it seems. Rebased.

@benthecarmanbenthecarman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

amazing!

@benthecarman
benthecarman merged commit 388ff9e into lightningdevkit:mainMay 8, 2026
11 checks passed
Sign up for freeto 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.

4 participants

@tnull@ldk-reviews-bot@benthecarman@github-advanced-security