Move ldk-server-mcp into the workspace#188
Move ldk-server-mcp into the workspace#188tnull wants to merge 21 commits intolightningdevkit:mainfrom
ldk-server-mcp into the workspace#188Conversation
|
🎉 This PR is now ready for review! |
70f8e5f to
3bc8a6e
Compare
benthecarman
left a comment
There was a problem hiding this comment.
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.
3bc8a6e to
8d6d7b0
Compare
b76ffeb to
b0292ff
Compare
| // 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 |
There was a problem hiding this comment.
any reason we aren't using the json decoder here? and in handle_verify_signature
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
I don't see us handling this anywhere, looks like we'd return METHOD_NOT_FOUND
There was a problem hiding this comment.
No, we just skip in main:
// Notifications have no id — do not respond
if request.id.is_none() {
continue;
}b0292ff to
9295c38
Compare
| 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 |
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
Support storage.disk.dir_path config and fall back to the default gRPC address when neither LDK_BASE_URL nor a config file is present, matching the behavior of ldk-server-cli. Co-Authored-By: HAL 9000
Fix clippy needless_borrows_for_generic_args in test. Co-Authored-By: HAL 9000
Move routing and invoice default constants into ldk-server-client so they are shared between ldk-server-cli and ldk-server-mcp. Co-Authored-By: HAL 9000
Move the shared config loading and credential resolution logic into ldk-server-client so that ldk-server-cli and ldk-server-mcp both consume the same implementation instead of duplicating path handling, TOML parsing, and API-key hex-encoding in each binary. Generated with the assistance of AI (Claude).
Use hex-conservative's DisplayHex implementation for encoding the pathfinding scores blob instead of a hand-rolled hex formatter so the crate matches the hex encoding already used elsewhere in the workspace. Generated with the assistance of AI (Claude).
Dispatch tool invocations through a HashMap keyed by tool name rather than scanning the full registry on every call, and emit compact JSON for tool responses instead of pretty-printing so the MCP bridge doesn't spend tokens on insignificant whitespace when piping results to an agent. Generated with the assistance of AI (Claude).
Probe the ldk-server with a GetNodeInfo call during startup so bad credentials or an unreachable base URL surface right away instead of only being discovered on the first tool call. The probe only logs a warning if it fails so the JSON-RPC loop still serves `initialize` and `tools/list` responses when the server is temporarily down. Generated with the assistance of AI (Claude).
Advertise the `2025-11-25` MCP protocol revision so the bridge reports the current protocol version rather than the older `2024-11-05` spec. Generated with the assistance of AI (Claude).
Classify tool handler errors with a dedicated `McpError` type that maps `LdkServerError` variants onto JSON-RPC error codes (`INVALID_PARAMS` for invalid-request errors, `INTERNAL_ERROR` for auth, Lightning and internal failures) and reuse those codes at the dispatch boundary so a `tools/call` request missing its `name` parameter returns a real JSON-RPC error instead of being silently routed as an "unknown tool". Handlers now propagate `LdkServerError` through a `From` conversion rather than cloning the error message. Generated with the assistance of AI (Claude).
Use the proto-generated `Deserialize` impls to parse each tool's arguments directly into the typed request struct, dropping the per-field `serde_json::Value` scaffolding and the handcrafted helpers for `Bolt11InvoiceDescription`, `ChannelConfig`, `RouteParametersConfig` and page tokens. `expiry_secs` still gets the MCP-side 24h default when omitted; `sign_message` and `verify_signature` keep a manual arg path since their proto `bytes` field cannot be deserialized from a JSON string. Tool JSON schemas are updated to describe the now-nested shapes for invoice descriptions, route parameters, channel configs, and page tokens. Generated with the assistance of AI (Claude).
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
Drop the tests/ directory from rerun-if-changed since test changes don't affect the mcp binary. Co-Authored-By: HAL 9000
Advertise the bumped `2025-11-25` MCP protocol version in the e2e test's initialize call so its assertion lines up with the server, and pull in the `hex-conservative` dependency that `ldk-server-client` started transitively pulling through its shared config module. Generated with the assistance of AI (Claude).
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
Remove redundant formatting check (already covered by the main CI workflow) and drop the MCP e2e job (already covered by the e2e-tests workflow). 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
Replace exhaustive tool listing with a pointer to tools/list to avoid the maintenance burden of keeping the README in sync with every new RPC. Co-Authored-By: HAL 9000
9295c38 to
9d74698
Compare
Moving from https://github.com/tnull/ldk-server-mcp
Draft for now.