handoff-mcp-server 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +25 -229
- package/Cargo.toml +2 -2
- package/README.md +116 -18
- package/package.json +1 -1
- package/scripts/handoff-memory-hook.py +6 -6
- package/skills/handoff/SKILL.md +17 -0
- package/src/cli.rs +551 -0
- package/src/lib.rs +2 -0
- package/src/main.rs +57 -0
- package/src/mcp/handlers/bulk_update.rs +1 -1
- package/src/mcp/handlers/check_criterion.rs +5 -6
- package/src/mcp/handlers/config.rs +38 -0
- package/src/mcp/handlers/get_task.rs +3 -6
- package/src/mcp/handlers/log_time.rs +3 -6
- package/src/mcp/handlers/mod.rs +8 -4
- package/src/mcp/handlers/timer.rs +529 -0
- package/src/mcp/handlers/update_task.rs +10 -21
- package/src/mcp/tools.rs +41 -4
- package/src/setup.rs +424 -0
- package/src/storage/config.rs +25 -0
- package/src/storage/tasks.rs +95 -4
package/Cargo.lock
CHANGED
|
@@ -13,9 +13,9 @@ dependencies = [
|
|
|
13
13
|
|
|
14
14
|
[[package]]
|
|
15
15
|
name = "anyhow"
|
|
16
|
-
version = "1.0.
|
|
16
|
+
version = "1.0.103"
|
|
17
17
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
18
|
-
checksum = "
|
|
18
|
+
checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3"
|
|
19
19
|
|
|
20
20
|
[[package]]
|
|
21
21
|
name = "autocfg"
|
|
@@ -37,9 +37,9 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
|
|
37
37
|
|
|
38
38
|
[[package]]
|
|
39
39
|
name = "cc"
|
|
40
|
-
version = "1.2.
|
|
40
|
+
version = "1.2.65"
|
|
41
41
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
42
|
-
checksum = "
|
|
42
|
+
checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96"
|
|
43
43
|
dependencies = [
|
|
44
44
|
"find-msvc-tools",
|
|
45
45
|
"shlex",
|
|
@@ -99,12 +99,6 @@ version = "0.1.9"
|
|
|
99
99
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
100
100
|
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
|
101
101
|
|
|
102
|
-
[[package]]
|
|
103
|
-
name = "foldhash"
|
|
104
|
-
version = "0.1.5"
|
|
105
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
106
|
-
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
|
107
|
-
|
|
108
102
|
[[package]]
|
|
109
103
|
name = "futures-core"
|
|
110
104
|
version = "0.3.32"
|
|
@@ -131,20 +125,18 @@ dependencies = [
|
|
|
131
125
|
|
|
132
126
|
[[package]]
|
|
133
127
|
name = "getrandom"
|
|
134
|
-
version = "0.4.
|
|
128
|
+
version = "0.4.3"
|
|
135
129
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
136
|
-
checksum = "
|
|
130
|
+
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
|
137
131
|
dependencies = [
|
|
138
132
|
"cfg-if",
|
|
139
133
|
"libc",
|
|
140
134
|
"r-efi",
|
|
141
|
-
"wasip2",
|
|
142
|
-
"wasip3",
|
|
143
135
|
]
|
|
144
136
|
|
|
145
137
|
[[package]]
|
|
146
138
|
name = "handoff-mcp"
|
|
147
|
-
version = "0.
|
|
139
|
+
version = "0.15.0"
|
|
148
140
|
dependencies = [
|
|
149
141
|
"anyhow",
|
|
150
142
|
"chrono",
|
|
@@ -157,27 +149,12 @@ dependencies = [
|
|
|
157
149
|
"toml_edit",
|
|
158
150
|
]
|
|
159
151
|
|
|
160
|
-
[[package]]
|
|
161
|
-
name = "hashbrown"
|
|
162
|
-
version = "0.15.5"
|
|
163
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
164
|
-
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
|
165
|
-
dependencies = [
|
|
166
|
-
"foldhash",
|
|
167
|
-
]
|
|
168
|
-
|
|
169
152
|
[[package]]
|
|
170
153
|
name = "hashbrown"
|
|
171
154
|
version = "0.17.1"
|
|
172
155
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
173
156
|
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
|
|
174
157
|
|
|
175
|
-
[[package]]
|
|
176
|
-
name = "heck"
|
|
177
|
-
version = "0.5.0"
|
|
178
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
179
|
-
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
180
|
-
|
|
181
158
|
[[package]]
|
|
182
159
|
name = "iana-time-zone"
|
|
183
160
|
version = "0.1.65"
|
|
@@ -202,12 +179,6 @@ dependencies = [
|
|
|
202
179
|
"cc",
|
|
203
180
|
]
|
|
204
181
|
|
|
205
|
-
[[package]]
|
|
206
|
-
name = "id-arena"
|
|
207
|
-
version = "2.3.0"
|
|
208
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
209
|
-
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
|
|
210
|
-
|
|
211
182
|
[[package]]
|
|
212
183
|
name = "indexmap"
|
|
213
184
|
version = "2.14.0"
|
|
@@ -215,9 +186,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
|
215
186
|
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
|
216
187
|
dependencies = [
|
|
217
188
|
"equivalent",
|
|
218
|
-
"hashbrown
|
|
219
|
-
"serde",
|
|
220
|
-
"serde_core",
|
|
189
|
+
"hashbrown",
|
|
221
190
|
]
|
|
222
191
|
|
|
223
192
|
[[package]]
|
|
@@ -228,21 +197,15 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
|
|
228
197
|
|
|
229
198
|
[[package]]
|
|
230
199
|
name = "js-sys"
|
|
231
|
-
version = "0.3.
|
|
200
|
+
version = "0.3.103"
|
|
232
201
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
233
|
-
checksum = "
|
|
202
|
+
checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102"
|
|
234
203
|
dependencies = [
|
|
235
204
|
"cfg-if",
|
|
236
205
|
"futures-util",
|
|
237
206
|
"wasm-bindgen",
|
|
238
207
|
]
|
|
239
208
|
|
|
240
|
-
[[package]]
|
|
241
|
-
name = "leb128fmt"
|
|
242
|
-
version = "0.1.0"
|
|
243
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
244
|
-
checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
|
245
|
-
|
|
246
209
|
[[package]]
|
|
247
210
|
name = "lexsim"
|
|
248
211
|
version = "0.1.0"
|
|
@@ -267,9 +230,9 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
|
|
|
267
230
|
|
|
268
231
|
[[package]]
|
|
269
232
|
name = "log"
|
|
270
|
-
version = "0.4.
|
|
233
|
+
version = "0.4.33"
|
|
271
234
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
272
|
-
checksum = "
|
|
235
|
+
checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
|
|
273
236
|
|
|
274
237
|
[[package]]
|
|
275
238
|
name = "memchr"
|
|
@@ -298,16 +261,6 @@ version = "0.2.17"
|
|
|
298
261
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
299
262
|
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
|
300
263
|
|
|
301
|
-
[[package]]
|
|
302
|
-
name = "prettyplease"
|
|
303
|
-
version = "0.2.37"
|
|
304
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
305
|
-
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
|
306
|
-
dependencies = [
|
|
307
|
-
"proc-macro2",
|
|
308
|
-
"syn",
|
|
309
|
-
]
|
|
310
|
-
|
|
311
264
|
[[package]]
|
|
312
265
|
name = "proc-macro2"
|
|
313
266
|
version = "1.0.106"
|
|
@@ -319,9 +272,9 @@ dependencies = [
|
|
|
319
272
|
|
|
320
273
|
[[package]]
|
|
321
274
|
name = "quote"
|
|
322
|
-
version = "1.0.
|
|
275
|
+
version = "1.0.46"
|
|
323
276
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
324
|
-
checksum = "
|
|
277
|
+
checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
|
|
325
278
|
dependencies = [
|
|
326
279
|
"proc-macro2",
|
|
327
280
|
]
|
|
@@ -351,12 +304,6 @@ version = "1.0.22"
|
|
|
351
304
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
352
305
|
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
|
353
306
|
|
|
354
|
-
[[package]]
|
|
355
|
-
name = "semver"
|
|
356
|
-
version = "1.0.28"
|
|
357
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
358
|
-
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
|
|
359
|
-
|
|
360
307
|
[[package]]
|
|
361
308
|
name = "serde"
|
|
362
309
|
version = "1.0.228"
|
|
@@ -393,6 +340,7 @@ version = "1.0.150"
|
|
|
393
340
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
394
341
|
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
|
|
395
342
|
dependencies = [
|
|
343
|
+
"indexmap",
|
|
396
344
|
"itoa",
|
|
397
345
|
"memchr",
|
|
398
346
|
"serde",
|
|
@@ -423,9 +371,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
|
|
423
371
|
|
|
424
372
|
[[package]]
|
|
425
373
|
name = "syn"
|
|
426
|
-
version = "2.0.
|
|
374
|
+
version = "2.0.118"
|
|
427
375
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
428
|
-
checksum = "
|
|
376
|
+
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
|
|
429
377
|
dependencies = [
|
|
430
378
|
"proc-macro2",
|
|
431
379
|
"quote",
|
|
@@ -542,35 +490,11 @@ version = "1.13.3"
|
|
|
542
490
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
543
491
|
checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8"
|
|
544
492
|
|
|
545
|
-
[[package]]
|
|
546
|
-
name = "unicode-xid"
|
|
547
|
-
version = "0.2.6"
|
|
548
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
549
|
-
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
|
550
|
-
|
|
551
|
-
[[package]]
|
|
552
|
-
name = "wasip2"
|
|
553
|
-
version = "1.0.4+wasi-0.2.12"
|
|
554
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
555
|
-
checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487"
|
|
556
|
-
dependencies = [
|
|
557
|
-
"wit-bindgen 0.57.1",
|
|
558
|
-
]
|
|
559
|
-
|
|
560
|
-
[[package]]
|
|
561
|
-
name = "wasip3"
|
|
562
|
-
version = "0.4.0+wasi-0.3.0-rc-2026-01-06"
|
|
563
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
564
|
-
checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"
|
|
565
|
-
dependencies = [
|
|
566
|
-
"wit-bindgen 0.51.0",
|
|
567
|
-
]
|
|
568
|
-
|
|
569
493
|
[[package]]
|
|
570
494
|
name = "wasm-bindgen"
|
|
571
|
-
version = "0.2.
|
|
495
|
+
version = "0.2.126"
|
|
572
496
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
573
|
-
checksum = "
|
|
497
|
+
checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4"
|
|
574
498
|
dependencies = [
|
|
575
499
|
"cfg-if",
|
|
576
500
|
"once_cell",
|
|
@@ -581,9 +505,9 @@ dependencies = [
|
|
|
581
505
|
|
|
582
506
|
[[package]]
|
|
583
507
|
name = "wasm-bindgen-macro"
|
|
584
|
-
version = "0.2.
|
|
508
|
+
version = "0.2.126"
|
|
585
509
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
586
|
-
checksum = "
|
|
510
|
+
checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1"
|
|
587
511
|
dependencies = [
|
|
588
512
|
"quote",
|
|
589
513
|
"wasm-bindgen-macro-support",
|
|
@@ -591,9 +515,9 @@ dependencies = [
|
|
|
591
515
|
|
|
592
516
|
[[package]]
|
|
593
517
|
name = "wasm-bindgen-macro-support"
|
|
594
|
-
version = "0.2.
|
|
518
|
+
version = "0.2.126"
|
|
595
519
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
596
|
-
checksum = "
|
|
520
|
+
checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e"
|
|
597
521
|
dependencies = [
|
|
598
522
|
"bumpalo",
|
|
599
523
|
"proc-macro2",
|
|
@@ -604,47 +528,13 @@ dependencies = [
|
|
|
604
528
|
|
|
605
529
|
[[package]]
|
|
606
530
|
name = "wasm-bindgen-shared"
|
|
607
|
-
version = "0.2.
|
|
531
|
+
version = "0.2.126"
|
|
608
532
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
609
|
-
checksum = "
|
|
533
|
+
checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24"
|
|
610
534
|
dependencies = [
|
|
611
535
|
"unicode-ident",
|
|
612
536
|
]
|
|
613
537
|
|
|
614
|
-
[[package]]
|
|
615
|
-
name = "wasm-encoder"
|
|
616
|
-
version = "0.244.0"
|
|
617
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
618
|
-
checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"
|
|
619
|
-
dependencies = [
|
|
620
|
-
"leb128fmt",
|
|
621
|
-
"wasmparser",
|
|
622
|
-
]
|
|
623
|
-
|
|
624
|
-
[[package]]
|
|
625
|
-
name = "wasm-metadata"
|
|
626
|
-
version = "0.244.0"
|
|
627
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
628
|
-
checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"
|
|
629
|
-
dependencies = [
|
|
630
|
-
"anyhow",
|
|
631
|
-
"indexmap",
|
|
632
|
-
"wasm-encoder",
|
|
633
|
-
"wasmparser",
|
|
634
|
-
]
|
|
635
|
-
|
|
636
|
-
[[package]]
|
|
637
|
-
name = "wasmparser"
|
|
638
|
-
version = "0.244.0"
|
|
639
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
640
|
-
checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"
|
|
641
|
-
dependencies = [
|
|
642
|
-
"bitflags",
|
|
643
|
-
"hashbrown 0.15.5",
|
|
644
|
-
"indexmap",
|
|
645
|
-
"semver",
|
|
646
|
-
]
|
|
647
|
-
|
|
648
538
|
[[package]]
|
|
649
539
|
name = "windows-core"
|
|
650
540
|
version = "0.62.2"
|
|
@@ -722,100 +612,6 @@ dependencies = [
|
|
|
722
612
|
"memchr",
|
|
723
613
|
]
|
|
724
614
|
|
|
725
|
-
[[package]]
|
|
726
|
-
name = "wit-bindgen"
|
|
727
|
-
version = "0.51.0"
|
|
728
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
729
|
-
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
|
|
730
|
-
dependencies = [
|
|
731
|
-
"wit-bindgen-rust-macro",
|
|
732
|
-
]
|
|
733
|
-
|
|
734
|
-
[[package]]
|
|
735
|
-
name = "wit-bindgen"
|
|
736
|
-
version = "0.57.1"
|
|
737
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
738
|
-
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
|
739
|
-
|
|
740
|
-
[[package]]
|
|
741
|
-
name = "wit-bindgen-core"
|
|
742
|
-
version = "0.51.0"
|
|
743
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
744
|
-
checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"
|
|
745
|
-
dependencies = [
|
|
746
|
-
"anyhow",
|
|
747
|
-
"heck",
|
|
748
|
-
"wit-parser",
|
|
749
|
-
]
|
|
750
|
-
|
|
751
|
-
[[package]]
|
|
752
|
-
name = "wit-bindgen-rust"
|
|
753
|
-
version = "0.51.0"
|
|
754
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
755
|
-
checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"
|
|
756
|
-
dependencies = [
|
|
757
|
-
"anyhow",
|
|
758
|
-
"heck",
|
|
759
|
-
"indexmap",
|
|
760
|
-
"prettyplease",
|
|
761
|
-
"syn",
|
|
762
|
-
"wasm-metadata",
|
|
763
|
-
"wit-bindgen-core",
|
|
764
|
-
"wit-component",
|
|
765
|
-
]
|
|
766
|
-
|
|
767
|
-
[[package]]
|
|
768
|
-
name = "wit-bindgen-rust-macro"
|
|
769
|
-
version = "0.51.0"
|
|
770
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
771
|
-
checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"
|
|
772
|
-
dependencies = [
|
|
773
|
-
"anyhow",
|
|
774
|
-
"prettyplease",
|
|
775
|
-
"proc-macro2",
|
|
776
|
-
"quote",
|
|
777
|
-
"syn",
|
|
778
|
-
"wit-bindgen-core",
|
|
779
|
-
"wit-bindgen-rust",
|
|
780
|
-
]
|
|
781
|
-
|
|
782
|
-
[[package]]
|
|
783
|
-
name = "wit-component"
|
|
784
|
-
version = "0.244.0"
|
|
785
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
786
|
-
checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"
|
|
787
|
-
dependencies = [
|
|
788
|
-
"anyhow",
|
|
789
|
-
"bitflags",
|
|
790
|
-
"indexmap",
|
|
791
|
-
"log",
|
|
792
|
-
"serde",
|
|
793
|
-
"serde_derive",
|
|
794
|
-
"serde_json",
|
|
795
|
-
"wasm-encoder",
|
|
796
|
-
"wasm-metadata",
|
|
797
|
-
"wasmparser",
|
|
798
|
-
"wit-parser",
|
|
799
|
-
]
|
|
800
|
-
|
|
801
|
-
[[package]]
|
|
802
|
-
name = "wit-parser"
|
|
803
|
-
version = "0.244.0"
|
|
804
|
-
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
805
|
-
checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"
|
|
806
|
-
dependencies = [
|
|
807
|
-
"anyhow",
|
|
808
|
-
"id-arena",
|
|
809
|
-
"indexmap",
|
|
810
|
-
"log",
|
|
811
|
-
"semver",
|
|
812
|
-
"serde",
|
|
813
|
-
"serde_derive",
|
|
814
|
-
"serde_json",
|
|
815
|
-
"unicode-xid",
|
|
816
|
-
"wasmparser",
|
|
817
|
-
]
|
|
818
|
-
|
|
819
615
|
[[package]]
|
|
820
616
|
name = "zmij"
|
|
821
617
|
version = "1.0.21"
|
package/Cargo.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "handoff-mcp"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.15.0"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
description = "MCP server that gives AI coding agents persistent memory across sessions"
|
|
6
6
|
license = "MIT"
|
|
@@ -14,7 +14,7 @@ exclude = ["lefthook.yml", "tmp/", "wiki/", "docs/", ".claude/", ".vscode/"]
|
|
|
14
14
|
|
|
15
15
|
[dependencies]
|
|
16
16
|
serde = { version = "1", features = ["derive"] }
|
|
17
|
-
serde_json = "1"
|
|
17
|
+
serde_json = { version = "1", features = ["preserve_order"] }
|
|
18
18
|
toml = "0.8"
|
|
19
19
|
toml_edit = "0.22"
|
|
20
20
|
chrono = { version = "0.4", features = ["serde"] }
|
package/README.md
CHANGED
|
@@ -33,12 +33,23 @@ At session start, the agent calls `handoff_load_context` to pick up where things
|
|
|
33
33
|
|
|
34
34
|
## Installation
|
|
35
35
|
|
|
36
|
-
###
|
|
36
|
+
### cargo (recommended if you have Rust)
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
cargo install handoff-mcp
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### npm
|
|
37
43
|
|
|
38
44
|
```bash
|
|
39
45
|
npm install -g handoff-mcp-server
|
|
40
46
|
```
|
|
41
47
|
|
|
48
|
+
Both install the same binary. `cargo install` fetches the crate from
|
|
49
|
+
[crates.io](https://crates.io/crates/handoff-mcp) and compiles it directly;
|
|
50
|
+
`npm install` downloads the source and runs `cargo build --release` via
|
|
51
|
+
postinstall, so either way you need a Rust toolchain.
|
|
52
|
+
|
|
42
53
|
### Build from source
|
|
43
54
|
|
|
44
55
|
```bash
|
|
@@ -73,6 +84,34 @@ The `-s user` flag registers it globally (available in all projects). Verify wit
|
|
|
73
84
|
}
|
|
74
85
|
```
|
|
75
86
|
|
|
87
|
+
### Enable automatic memory injection (optional)
|
|
88
|
+
|
|
89
|
+
If you want project memories to be automatically injected into your context
|
|
90
|
+
(instead of calling `handoff_memory_query` manually every time), run:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
handoff-mcp setup
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
This installs Claude Code hooks into `~/.claude/settings.json` that
|
|
97
|
+
automatically call `handoff_memory_query` on every prompt and file edit, and run
|
|
98
|
+
`handoff_memory_cleanup` at session start. Restart Claude Code after running setup.
|
|
99
|
+
|
|
100
|
+
You can check the current status or remove the hooks:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
handoff-mcp setup --check # Show hook status
|
|
104
|
+
handoff-mcp setup --uninstall # Remove handoff hooks
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The hooks fire on every prompt and file edit, which adds a small overhead per
|
|
108
|
+
interaction. If you want to stop automatic injection, run
|
|
109
|
+
`handoff-mcp setup --uninstall` — the memory tools themselves remain available
|
|
110
|
+
for manual use, only the automatic hooks are removed.
|
|
111
|
+
|
|
112
|
+
See [Automatic injection via hooks](#automatic-injection-via-hooks) for the
|
|
113
|
+
manual configuration alternative.
|
|
114
|
+
|
|
76
115
|
## Quick Start
|
|
77
116
|
|
|
78
117
|
1. **Initialize** a project:
|
|
@@ -159,14 +198,22 @@ rename) so a concurrent reader never sees a partially-written file.
|
|
|
159
198
|
| `handoff_get_referral` | Fetch one incoming referral in full — details, suggested tasks, done_criteria, context |
|
|
160
199
|
| `handoff_update_referral` | Update referral status (open → acknowledged → resolved) |
|
|
161
200
|
|
|
201
|
+
### Timer Coordination
|
|
202
|
+
|
|
203
|
+
| Tool | Purpose |
|
|
204
|
+
|------|---------|
|
|
205
|
+
| `handoff_timer_start` | Start tracking time for a task — delegates to VSCode extension if alive, otherwise starts MCP fallback timer |
|
|
206
|
+
| `handoff_timer_stop` | Stop the timer and log elapsed hours to `actual_hours` — delegates to VSCode if alive |
|
|
207
|
+
| `handoff_timer_get_time` | Get current timer state (elapsed, authority, projected total) without stopping |
|
|
208
|
+
|
|
162
209
|
### Project Memory
|
|
163
210
|
|
|
164
211
|
| Tool | Purpose |
|
|
165
212
|
|------|---------|
|
|
166
|
-
| `
|
|
167
|
-
| `
|
|
168
|
-
| `
|
|
169
|
-
| `
|
|
213
|
+
| `handoff_memory_save` | Save a durable project memory (lesson/rule/convention/gotcha); detects exact and near-duplicate memories and hands near-duplicates back for AI-driven merge |
|
|
214
|
+
| `handoff_memory_query` | Return the memories most relevant to the current prompt/file (BM25 + scope-path boost); with a `session_id`, suppresses repeats already injected this session |
|
|
215
|
+
| `handoff_memory_delete` | Delete a memory by id (full id or unique prefix) |
|
|
216
|
+
| `handoff_memory_cleanup` | Housekeeping (for SessionStart): silently merge exact duplicates, return near-duplicate/stale recommendations, gc old injection sidecars |
|
|
170
217
|
|
|
171
218
|
See [Project Memory](#project-memory-1) below for what it is and how to wire automatic injection.
|
|
172
219
|
|
|
@@ -240,6 +287,9 @@ done_task_limit = 10 # Max completed tasks to show
|
|
|
240
287
|
auto_git_summary = true # Capture git state automatically
|
|
241
288
|
require_estimate_hours = true # Require estimate_hours on leaf tasks (default true)
|
|
242
289
|
ai_estimate_multiplier = 0.2 # Multiplier turning human estimates into AI-effort hours
|
|
290
|
+
timer_provider = "auto" # "auto" | "vscode" | "mcp" | "off"
|
|
291
|
+
timer_authority_ttl_secs = 30 # Heartbeat freshness TTL for authority.json
|
|
292
|
+
timer_idle_timeout_minutes = 10 # Idle pause threshold for MCP fallback timer
|
|
243
293
|
|
|
244
294
|
[dashboard]
|
|
245
295
|
scan_dirs = ["~/pro/"] # Directories to scan for dashboard
|
|
@@ -300,6 +350,11 @@ Sessions answer *"what was I doing last time?"*. **Memory** answers a longer-liv
|
|
|
300
350
|
question: *"what should every session in this project always know?"* — durable
|
|
301
351
|
lessons, rules, conventions, and gotchas that outlive any one session.
|
|
302
352
|
|
|
353
|
+
> **Note:** The memory tools (`handoff_memory_save`, `handoff_memory_query`, etc.) can always be
|
|
354
|
+
> called directly by the agent. For **automatic** injection — where relevant
|
|
355
|
+
> memories are surfaced on every prompt without the agent asking — you need to
|
|
356
|
+
> configure Claude Code hooks. See [Automatic injection via hooks](#automatic-injection-via-hooks).
|
|
357
|
+
|
|
303
358
|
Memories live in `.handoff/memory/` (one JSON file per memory, plus per-session
|
|
304
359
|
`injected/` sidecars). A built-in multilingual similarity engine (Japanese /
|
|
305
360
|
English, dictionary-free) ranks relevance and detects duplicates, all in-memory
|
|
@@ -309,28 +364,28 @@ and sub-millisecond.
|
|
|
309
364
|
|
|
310
365
|
The agent can call the memory tools at any time:
|
|
311
366
|
|
|
312
|
-
- `
|
|
367
|
+
- `handoff_memory_save` — record a memory. An exact duplicate is reported (not
|
|
313
368
|
rewritten); a near-duplicate comes back as a `conflict` with both bodies so the
|
|
314
369
|
agent can merge them (`merge_into=<id>`, `absorb_ids=[…]`) or save separately
|
|
315
370
|
with `force=true`. **handoff-mcp never merges for you** — it surfaces both
|
|
316
371
|
bodies and lets the agent decide.
|
|
317
|
-
- `
|
|
318
|
-
- `
|
|
372
|
+
- `handoff_memory_query` — fetch the memories most relevant to some text and/or files.
|
|
373
|
+
- `handoff_memory_delete` / `handoff_memory_cleanup` — prune and de-duplicate the store.
|
|
319
374
|
|
|
320
375
|
### Automatic injection via hooks
|
|
321
376
|
|
|
322
377
|
MCP is request/response — the server cannot push a memory into the agent's
|
|
323
378
|
context on its own. **Claude Code hooks** close that gap: they fire regardless of
|
|
324
|
-
what the agent intends, call `
|
|
379
|
+
what the agent intends, call `handoff_memory_query`, and inject the matching memories as
|
|
325
380
|
`additionalContext`. A per-session diff (keyed on the hook `session_id`) ensures
|
|
326
381
|
the same memory is **not injected twice in one session** — and an *edited* memory
|
|
327
382
|
(new content hash) is re-injected.
|
|
328
383
|
|
|
329
384
|
| Event | Calls | Effect |
|
|
330
385
|
|-------|-------|--------|
|
|
331
|
-
| `UserPromptSubmit` | `
|
|
332
|
-
| `PreToolUse` (`Edit\|Write\|MultiEdit`) | `
|
|
333
|
-
| `SessionStart` | `
|
|
386
|
+
| `UserPromptSubmit` | `handoff_memory_query` (prompt text) | Inject memories relevant to the prompt |
|
|
387
|
+
| `PreToolUse` (`Edit\|Write\|MultiEdit`) | `handoff_memory_query` (file path) | Inject memories scoped to the file being edited |
|
|
388
|
+
| `SessionStart` | `handoff_memory_cleanup` | Merge exact duplicates, gc old sidecars |
|
|
334
389
|
|
|
335
390
|
> **Wire hooks in your *user/global* settings, not in the repo.** Hooks are a
|
|
336
391
|
> personal workflow choice; the handoff-mcp repo does not ship a `.claude/`
|
|
@@ -347,14 +402,14 @@ MCP tool from a hook directly, with no wrapper script. In
|
|
|
347
402
|
"hooks": {
|
|
348
403
|
"UserPromptSubmit": [
|
|
349
404
|
{ "hooks": [ {
|
|
350
|
-
"type": "mcp_tool", "server": "handoff", "tool": "
|
|
405
|
+
"type": "mcp_tool", "server": "handoff", "tool": "handoff_memory_query",
|
|
351
406
|
"input": { "project_dir": "${cwd}",
|
|
352
407
|
"session_id": "${session_id}", "text": "${prompt}" }
|
|
353
408
|
} ] }
|
|
354
409
|
],
|
|
355
410
|
"PreToolUse": [
|
|
356
411
|
{ "matcher": "Edit|Write|MultiEdit", "hooks": [ {
|
|
357
|
-
"type": "mcp_tool", "server": "handoff", "tool": "
|
|
412
|
+
"type": "mcp_tool", "server": "handoff", "tool": "handoff_memory_query",
|
|
358
413
|
"input": { "project_dir": "${cwd}",
|
|
359
414
|
"session_id": "${session_id}", "tool_name": "${tool_name}",
|
|
360
415
|
"text": "${tool_input.file_path}",
|
|
@@ -363,7 +418,7 @@ MCP tool from a hook directly, with no wrapper script. In
|
|
|
363
418
|
],
|
|
364
419
|
"SessionStart": [
|
|
365
420
|
{ "hooks": [ {
|
|
366
|
-
"type": "mcp_tool", "server": "handoff", "tool": "
|
|
421
|
+
"type": "mcp_tool", "server": "handoff", "tool": "handoff_memory_cleanup",
|
|
367
422
|
"input": { "project_dir": "${cwd}" }
|
|
368
423
|
} ] }
|
|
369
424
|
]
|
|
@@ -413,11 +468,50 @@ All under `[settings]` in `.handoff/config.toml`, all with safe defaults
|
|
|
413
468
|
|-----|---------|---------|
|
|
414
469
|
| `memory_enabled` | `true` | Master switch. When `false`, all four memory tools return a benign empty result and write nothing |
|
|
415
470
|
| `memory_dup_threshold` | `0.72` | Jaccard similarity at/above which a save is a near-duplicate conflict and cleanup groups a cluster |
|
|
416
|
-
| `memory_query_min_score` | `0.5` | BM25 relevance floor for `
|
|
471
|
+
| `memory_query_min_score` | `0.5` | BM25 relevance floor for `handoff_memory_query` results |
|
|
417
472
|
| `memory_query_limit` | `5` | Max memories returned per query |
|
|
418
473
|
| `memory_stale_days` | `60` | Days without a reference before a memory is flagged stale |
|
|
419
474
|
| `memory_injected_gc_days` | `14` | Age at which per-session injection sidecars are garbage-collected |
|
|
420
475
|
|
|
476
|
+
## CLI API
|
|
477
|
+
|
|
478
|
+
Since v0.15.0, every MCP tool is also callable directly from the shell:
|
|
479
|
+
|
|
480
|
+
```bash
|
|
481
|
+
handoff-mcp <group> <action> [--key value ...]
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
All output is JSON on stdout, suitable for scripting and programmatic use
|
|
485
|
+
(e.g. `child_process.execFile` from a VSCode extension).
|
|
486
|
+
|
|
487
|
+
**Examples:**
|
|
488
|
+
|
|
489
|
+
```bash
|
|
490
|
+
# Memory operations
|
|
491
|
+
handoff-mcp memory save --text "Always use atomic_write" --kind lesson --tags safety,io
|
|
492
|
+
handoff-mcp memory query --text "atomic" --limit 5
|
|
493
|
+
handoff-mcp memory delete --id m-20260630-...
|
|
494
|
+
|
|
495
|
+
# Task management
|
|
496
|
+
handoff-mcp task list --status-filter todo
|
|
497
|
+
handoff-mcp task update --id t1 --title "New task" --status todo --estimate-hours 2
|
|
498
|
+
handoff-mcp task log-time --task-id t1 --hours 0.5
|
|
499
|
+
|
|
500
|
+
# Session and metrics
|
|
501
|
+
handoff-mcp session load
|
|
502
|
+
handoff-mcp metrics
|
|
503
|
+
handoff-mcp dashboard
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
**Available groups:** `init`, `task`, `session`, `config`, `memory`,
|
|
507
|
+
`referral`, `assignee`, `milestone`, `calendar`, `labels`, `project`,
|
|
508
|
+
`metrics`, `capacity`, `schedule`, `dashboard`, `timer`.
|
|
509
|
+
|
|
510
|
+
Run `handoff-mcp --help` to see all groups, or `handoff-mcp <group> --help`
|
|
511
|
+
for actions within a group. See the
|
|
512
|
+
[CLI API Reference](https://github.com/alphaelements/handoff-mcp/wiki/CLI-API-Reference)
|
|
513
|
+
on the wiki for the full command list.
|
|
514
|
+
|
|
421
515
|
## MCP Resources
|
|
422
516
|
|
|
423
517
|
| URI | Description |
|
|
@@ -445,9 +539,13 @@ This project uses handoff-mcp for session continuity.
|
|
|
445
539
|
- **Decisions**: Record decisions with confidence levels as they are made,
|
|
446
540
|
not just at session end. Use `confirmed` for verified facts, `estimated`
|
|
447
541
|
for reasonable assumptions, `unverified` for unknowns.
|
|
448
|
-
- **
|
|
542
|
+
- **Timer**: Use `handoff_timer_start` / `handoff_timer_stop` to track task time.
|
|
543
|
+
When the VSCode extension is running, the timer delegates to it automatically.
|
|
544
|
+
When the extension is absent, MCP runs a fallback timer and logs hours on stop.
|
|
545
|
+
Use `handoff_timer_get_time` to check elapsed time without stopping.
|
|
546
|
+
- **Project memory**: Use `handoff_memory_save` to record durable lessons, rules,
|
|
449
547
|
conventions, and gotchas that every future session should know. Use
|
|
450
|
-
`
|
|
548
|
+
`handoff_memory_query` to retrieve relevant memories. Near-duplicate memories are
|
|
451
549
|
surfaced as conflicts for you to merge or force-save — never merged silently.
|
|
452
550
|
```
|
|
453
551
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "handoff-mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "MCP server that gives AI coding agents persistent memory across sessions",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "AlphaElements <66808803+alphaelements@users.noreply.github.com>",
|