feat: add docker setup
This commit is contained in:
6
.dockerignore
Normal file
6
.dockerignore
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
*
|
||||||
|
!src/
|
||||||
|
!migrations/
|
||||||
|
!build.rs
|
||||||
|
!Cargo.toml
|
||||||
|
!Cargo.lock
|
||||||
21
Cargo.lock
generated
21
Cargo.lock
generated
@@ -376,6 +376,16 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.3.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.60.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "etcetera"
|
name = "etcetera"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@@ -1193,6 +1203,16 @@ version = "1.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-registry"
|
||||||
|
version = "1.4.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
|
||||||
|
dependencies = [
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signature"
|
name = "signature"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
@@ -1561,6 +1581,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
"signal-hook-registry",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ dirs = "6"
|
|||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
sqlx = { version = "0.8", features = ["runtime-tokio", "sqlite", "chrono", "migrate"] }
|
sqlx = { version = "0.8", features = ["runtime-tokio", "sqlite", "chrono", "migrate"] }
|
||||||
tokio = { version = "1", features = ["rt", "macros"] }
|
tokio = { version = "1", features = ["rt", "macros", "io-std", "io-util", "signal"] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
|
|||||||
9
Dockerfile
Normal file
9
Dockerfile
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
FROM rust:1.85 AS build
|
||||||
|
WORKDIR /src
|
||||||
|
COPY . .
|
||||||
|
ENV SQLX_OFFLINE=true
|
||||||
|
RUN cargo build --release --bin todo-mcp
|
||||||
|
|
||||||
|
FROM gcr.io/distroless/cc-debian12
|
||||||
|
COPY --from=build /src/target/release/todo-mcp /
|
||||||
|
ENTRYPOINT ["/todo-mcp"]
|
||||||
32
README.md
32
README.md
@@ -62,10 +62,18 @@ todo-mcp tags
|
|||||||
todo-mcp purge
|
todo-mcp purge
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Docker
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker build -t local/todo-mcp .
|
||||||
|
docker run --rm -v todo-mcp-data:/data -e TODO_DB=/data/todos.db local/todo-mcp --help
|
||||||
|
```
|
||||||
|
|
||||||
|
Data is persisted in the `todo-mcp-data` volume. See [Usage](#usage) for more commands.
|
||||||
|
|
||||||
## Claude Setup
|
## Claude Setup
|
||||||
|
|
||||||
todo-mcp ships with an MCP server that lets Claude manage your todos. Add this
|
### Native
|
||||||
to your Claude MCP config:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -78,5 +86,25 @@ to your Claude MCP config:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Docker
|
||||||
|
|
||||||
|
Build the image first (see [Docker](#docker)), then add to your Claude MCP config:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"todo": {
|
||||||
|
"command": "docker",
|
||||||
|
"args": [
|
||||||
|
"run", "-i", "--rm",
|
||||||
|
"-v", "todo-mcp-data:/data",
|
||||||
|
"-e", "TODO_DB=/data/todos.db",
|
||||||
|
"local/todo-mcp", "mcp-serve"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
This gives Claude access to all todo operations — adding, listing, completing,
|
This gives Claude access to all todo operations — adding, listing, completing,
|
||||||
editing, removing, and purging.
|
editing, removing, and purging.
|
||||||
|
|||||||
17
src/mcp.rs
17
src/mcp.rs
@@ -1,8 +1,9 @@
|
|||||||
use std::io::{self, BufRead, Write};
|
use std::io::{self, Write};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
use tokio::io::{AsyncBufReadExt, BufReader};
|
||||||
|
|
||||||
use crate::db::{self, ListFilters, Pool};
|
use crate::db::{self, ListFilters, Pool};
|
||||||
use crate::model::Priority;
|
use crate::model::Priority;
|
||||||
@@ -233,11 +234,19 @@ async fn dispatch(pool: &Pool, name: &str, args: &Value) -> Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn serve(pool: &Pool) -> Result<()> {
|
pub async fn serve(pool: &Pool) -> Result<()> {
|
||||||
let stdin = io::stdin().lock();
|
let stdin = BufReader::new(tokio::io::stdin());
|
||||||
let mut stdout = io::stdout().lock();
|
let mut stdout = io::stdout().lock();
|
||||||
|
let mut lines = stdin.lines();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let line: String = tokio::select! {
|
||||||
|
line = lines.next_line() => match line? {
|
||||||
|
Some(line) => line,
|
||||||
|
None => break,
|
||||||
|
},
|
||||||
|
_ = tokio::signal::ctrl_c() => break,
|
||||||
|
};
|
||||||
|
|
||||||
for line in stdin.lines() {
|
|
||||||
let line = line?;
|
|
||||||
if line.is_empty() {
|
if line.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user