Compare commits
10 Commits
37d4ab92c3
...
b4bbbd28ef
| Author | SHA1 | Date | |
|---|---|---|---|
| b4bbbd28ef | |||
| 554082f88c | |||
| 9787993c7e | |||
| 2b2371a6c5 | |||
| 4d2ff19d41 | |||
| a849f8e929 | |||
| 24a1ae6ef9 | |||
| 212de0524e | |||
| 10879e431c | |||
| afe623d5a8 |
45
README.md
45
README.md
@ -1,43 +1,4 @@
|
|||||||
# Mcp
|
# Ruby MCP Client Implementation
|
||||||
|
|
||||||
TODO: Delete this and the text below, and describe your gem
|
This is a small MCP client implementation for ruby. It is probably not what you want to actually
|
||||||
|
use as it needlessly wraps a rust implementation of JSON-RPC as a learning exercise.
|
||||||
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/mcp`. To experiment with that code, run `bin/console` for an interactive prompt.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
|
|
||||||
|
|
||||||
Install the gem and add to the application's Gemfile by executing:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
|
|
||||||
```
|
|
||||||
|
|
||||||
If bundler is not being used to manage dependencies, install the gem by executing:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
TODO: Write usage instructions here
|
|
||||||
|
|
||||||
## Development
|
|
||||||
|
|
||||||
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
||||||
|
|
||||||
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/mcp. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/mcp/blob/main/CODE_OF_CONDUCT.md).
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
||||||
|
|
||||||
## Code of Conduct
|
|
||||||
|
|
||||||
Everyone interacting in the Mcp project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/mcp/blob/main/CODE_OF_CONDUCT.md).
|
|
||||||
|
|||||||
559
ext/mcp/Cargo.lock
generated
559
ext/mcp/Cargo.lock
generated
@ -79,7 +79,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"regex",
|
"regex",
|
||||||
"rustc-hash",
|
"rustc-hash 1.1.0",
|
||||||
"shlex",
|
"shlex",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
@ -122,17 +122,6 @@ dependencies = [
|
|||||||
"libloading",
|
"libloading",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "displaydoc"
|
|
||||||
version = "0.2.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.15.0"
|
version = "1.15.0"
|
||||||
@ -140,12 +129,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "form_urlencoded"
|
name = "fnv"
|
||||||
version = "1.2.1"
|
version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-sink"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-task"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-timer"
|
||||||
|
version = "3.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-util"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"percent-encoding",
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"pin-project-lite",
|
||||||
|
"pin-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -161,142 +184,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
|
checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icu_collections"
|
name = "http"
|
||||||
version = "1.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
|
|
||||||
dependencies = [
|
|
||||||
"displaydoc",
|
|
||||||
"yoke",
|
|
||||||
"zerofrom",
|
|
||||||
"zerovec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_locid"
|
|
||||||
version = "1.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
|
|
||||||
dependencies = [
|
|
||||||
"displaydoc",
|
|
||||||
"litemap",
|
|
||||||
"tinystr",
|
|
||||||
"writeable",
|
|
||||||
"zerovec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_locid_transform"
|
|
||||||
version = "1.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
|
|
||||||
dependencies = [
|
|
||||||
"displaydoc",
|
|
||||||
"icu_locid",
|
|
||||||
"icu_locid_transform_data",
|
|
||||||
"icu_provider",
|
|
||||||
"tinystr",
|
|
||||||
"zerovec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_locid_transform_data"
|
|
||||||
version = "1.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_normalizer"
|
|
||||||
version = "1.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
|
|
||||||
dependencies = [
|
|
||||||
"displaydoc",
|
|
||||||
"icu_collections",
|
|
||||||
"icu_normalizer_data",
|
|
||||||
"icu_properties",
|
|
||||||
"icu_provider",
|
|
||||||
"smallvec",
|
|
||||||
"utf16_iter",
|
|
||||||
"utf8_iter",
|
|
||||||
"write16",
|
|
||||||
"zerovec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_normalizer_data"
|
|
||||||
version = "1.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_properties"
|
|
||||||
version = "1.5.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
|
|
||||||
dependencies = [
|
|
||||||
"displaydoc",
|
|
||||||
"icu_collections",
|
|
||||||
"icu_locid_transform",
|
|
||||||
"icu_properties_data",
|
|
||||||
"icu_provider",
|
|
||||||
"tinystr",
|
|
||||||
"zerovec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_properties_data"
|
|
||||||
version = "1.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_provider"
|
|
||||||
version = "1.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
|
|
||||||
dependencies = [
|
|
||||||
"displaydoc",
|
|
||||||
"icu_locid",
|
|
||||||
"icu_provider_macros",
|
|
||||||
"stable_deref_trait",
|
|
||||||
"tinystr",
|
|
||||||
"writeable",
|
|
||||||
"yoke",
|
|
||||||
"zerofrom",
|
|
||||||
"zerovec",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "icu_provider_macros"
|
|
||||||
version = "1.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "idna"
|
|
||||||
version = "1.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
|
|
||||||
dependencies = [
|
|
||||||
"idna_adapter",
|
|
||||||
"smallvec",
|
|
||||||
"utf8_iter",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "idna_adapter"
|
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
|
checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"icu_normalizer",
|
"bytes",
|
||||||
"icu_properties",
|
"fnv",
|
||||||
|
"itoa",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -314,6 +209,48 @@ version = "1.0.15"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jsonrpsee"
|
||||||
|
version = "0.24.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "834af00800e962dee8f7bfc0f60601de215e73e78e5497d733a2919da837d3c8"
|
||||||
|
dependencies = [
|
||||||
|
"jsonrpsee-core",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jsonrpsee-core"
|
||||||
|
version = "0.24.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76637f6294b04e747d68e69336ef839a3493ca62b35bf488ead525f7da75c5bb"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"futures-timer",
|
||||||
|
"futures-util",
|
||||||
|
"jsonrpsee-types",
|
||||||
|
"pin-project",
|
||||||
|
"rustc-hash 2.1.1",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"tokio-stream",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jsonrpsee-types"
|
||||||
|
version = "0.24.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ddb81adb1a5ae9182df379e374a79e24e992334e7346af4d065ae5b2acb8d4c6"
|
||||||
|
dependencies = [
|
||||||
|
"http",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
@ -342,12 +279,6 @@ dependencies = [
|
|||||||
"windows-targets",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "litemap"
|
|
||||||
version = "0.7.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.12"
|
version = "0.4.12"
|
||||||
@ -358,6 +289,12 @@ dependencies = [
|
|||||||
"scopeguard",
|
"scopeguard",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "magnus"
|
name = "magnus"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@ -382,26 +319,28 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mcp"
|
name = "matchers"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"magnus",
|
"regex-automata 0.1.10",
|
||||||
"mcp-sdk",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mcp-sdk"
|
name = "mcp"
|
||||||
version = "0.0.3"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "95ec0bb3052aef37a76f074f185d50bb165662c1f5beccab6719bc0386a4fd29"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"jsonrpsee",
|
||||||
|
"magnus",
|
||||||
|
"once_cell",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"serde_magnus",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"url",
|
"tracing-subscriber",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -446,6 +385,16 @@ dependencies = [
|
|||||||
"minimal-lexical",
|
"minimal-lexical",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nu-ansi-term"
|
||||||
|
version = "0.46.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
|
||||||
|
dependencies = [
|
||||||
|
"overload",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.36.7"
|
version = "0.36.7"
|
||||||
@ -461,6 +410,12 @@ version = "1.21.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc"
|
checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "overload"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
@ -485,10 +440,24 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "pin-project"
|
||||||
version = "2.3.1"
|
version = "1.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
checksum = "dfe2e71e1471fe07709406bf725f710b02927c9c54b2b5b2ec0e8087d97c327d"
|
||||||
|
dependencies = [
|
||||||
|
"pin-project-internal",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-internal"
|
||||||
|
version = "1.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f6e859e6e5bd50440ab63c47e3ebabc90f26251f7c73c3d3e837b74a1cc3fa67"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
@ -496,6 +465,12 @@ version = "0.2.16"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-utils"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.94"
|
version = "1.0.94"
|
||||||
@ -561,8 +536,17 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-automata",
|
"regex-automata 0.4.9",
|
||||||
"regex-syntax",
|
"regex-syntax 0.8.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
|
||||||
|
dependencies = [
|
||||||
|
"regex-syntax 0.6.29",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -573,9 +557,15 @@ checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
"regex-syntax",
|
"regex-syntax 0.8.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.6.29"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.8.5"
|
version = "0.8.5"
|
||||||
@ -594,6 +584,12 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-hash"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.20"
|
version = "1.0.20"
|
||||||
@ -644,6 +640,26 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_magnus"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "51b8b945a2dadb221f1c5490cfb411cab6c3821446b8eca50ee07e5a3893ec51"
|
||||||
|
dependencies = [
|
||||||
|
"magnus",
|
||||||
|
"serde",
|
||||||
|
"tap",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sharded-slab"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shell-words"
|
name = "shell-words"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@ -681,12 +697,6 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stable_deref_trait"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.100"
|
version = "2.0.100"
|
||||||
@ -699,10 +709,25 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "synstructure"
|
name = "tap"
|
||||||
version = "0.13.1"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
|
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.69"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -710,13 +735,13 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinystr"
|
name = "thread_local"
|
||||||
version = "0.7.6"
|
version = "1.1.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
|
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"displaydoc",
|
"cfg-if",
|
||||||
"zerovec",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -748,6 +773,17 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-stream"
|
||||||
|
version = "0.1.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.41"
|
version = "0.1.41"
|
||||||
@ -777,6 +813,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
|
checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"valuable",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-log"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"tracing-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tracing-subscriber"
|
||||||
|
version = "0.3.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
|
||||||
|
dependencies = [
|
||||||
|
"matchers",
|
||||||
|
"nu-ansi-term",
|
||||||
|
"once_cell",
|
||||||
|
"regex",
|
||||||
|
"sharded-slab",
|
||||||
|
"smallvec",
|
||||||
|
"thread_local",
|
||||||
|
"tracing",
|
||||||
|
"tracing-core",
|
||||||
|
"tracing-log",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -786,28 +852,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "valuable"
|
||||||
version = "2.5.4"
|
version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
|
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
|
||||||
dependencies = [
|
|
||||||
"form_urlencoded",
|
|
||||||
"idna",
|
|
||||||
"percent-encoding",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "utf16_iter"
|
|
||||||
version = "1.0.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "utf8_iter"
|
|
||||||
version = "1.0.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
@ -815,6 +863,28 @@ version = "0.11.0+wasi-snapshot-preview1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
@ -887,82 +957,3 @@ name = "windows_x86_64_msvc"
|
|||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "write16"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "writeable"
|
|
||||||
version = "0.5.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "yoke"
|
|
||||||
version = "0.7.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
"stable_deref_trait",
|
|
||||||
"yoke-derive",
|
|
||||||
"zerofrom",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "yoke-derive"
|
|
||||||
version = "0.7.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"synstructure",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zerofrom"
|
|
||||||
version = "0.1.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
|
|
||||||
dependencies = [
|
|
||||||
"zerofrom-derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zerofrom-derive"
|
|
||||||
version = "0.1.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
"synstructure",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zerovec"
|
|
||||||
version = "0.10.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
|
|
||||||
dependencies = [
|
|
||||||
"yoke",
|
|
||||||
"zerofrom",
|
|
||||||
"zerovec-derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zerovec-derive"
|
|
||||||
version = "0.10.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|||||||
@ -3,9 +3,21 @@ name = "mcp"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "internal-test"
|
||||||
|
path = "src/internal-test.rs"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
magnus = "0.7"
|
jsonrpsee = { version = "0.24.8", features = ["async-client", "client-core", "tracing"] }
|
||||||
mcp-sdk = "0.0.3"
|
magnus = { version = "0.7", features = ["default"] }
|
||||||
|
tokio = { version = "1.44.1", features = ["full"] }
|
||||||
|
anyhow = "1.0.97"
|
||||||
|
tracing = "0.1.41"
|
||||||
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
|
serde_json = "1.0.140"
|
||||||
|
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
|
||||||
|
once_cell = "1.19.0"
|
||||||
|
serde_magnus = "0.9.0"
|
||||||
|
|||||||
2076
ext/mcp/schema.json
Normal file
2076
ext/mcp/schema.json
Normal file
File diff suppressed because it is too large
Load Diff
61
ext/mcp/src/internal-test.rs
Normal file
61
ext/mcp/src/internal-test.rs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
use std::process::Stdio;
|
||||||
|
use jsonrpsee::core::client::{
|
||||||
|
Client, ClientBuilder, ClientT, TransportReceiverT, TransportSenderT,
|
||||||
|
};
|
||||||
|
use jsonrpsee::core::traits::ToRpcParams;
|
||||||
|
use tokio::io::{AsyncBufReadExt, AsyncWriteExt};
|
||||||
|
use serde::Serialize;
|
||||||
|
use serde_json::json;
|
||||||
|
use types::{Implementation, InitializeRequestParams, InitializeResult};
|
||||||
|
use crate::types::{CallToolRequestParams, ClientCapabilities, ListToolsRequestParams, ListToolsResult};
|
||||||
|
|
||||||
|
mod types;
|
||||||
|
mod rpc_helpers;
|
||||||
|
mod stdio_transport;
|
||||||
|
|
||||||
|
use rpc_helpers::*;
|
||||||
|
use stdio_transport::StdioTransport;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> anyhow::Result<()> {
|
||||||
|
tracing_subscriber::fmt()
|
||||||
|
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
|
||||||
|
.with_file(true)
|
||||||
|
.with_line_number(true)
|
||||||
|
.with_thread_ids(true)
|
||||||
|
.with_thread_names(true)
|
||||||
|
.with_target(true)
|
||||||
|
.with_level(true)
|
||||||
|
.init();
|
||||||
|
|
||||||
|
let cmd = tokio::process::Command::new("/Users/joshuacoles/.local/bin/mcp-server-fetch")
|
||||||
|
.stdin(Stdio::piped())
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.spawn()?;
|
||||||
|
|
||||||
|
let transport = StdioTransport::new(cmd);
|
||||||
|
|
||||||
|
let client: Client = ClientBuilder::default().build_with_tokio(
|
||||||
|
transport.clone(),
|
||||||
|
transport.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let response: InitializeResult = client.request("initialize", InitializeRequestParams {
|
||||||
|
capabilities: ClientCapabilities::default(),
|
||||||
|
client_info: Implementation { name: "Rust MCP".to_string(), version: "0.1.0".to_string() },
|
||||||
|
protocol_version: "2024-11-05".to_string(),
|
||||||
|
}.to_rpc()).await?;
|
||||||
|
|
||||||
|
client.notification("notifications/initialized", NoParams).await?;
|
||||||
|
|
||||||
|
let response: ListToolsResult = client.request("tools/list", ListToolsRequestParams::default().to_rpc()).await?;
|
||||||
|
|
||||||
|
let response: serde_json::Value = client.request("tools/call", CallToolRequestParams {
|
||||||
|
arguments: json!({ "url": "http://example.com" }).as_object().unwrap().clone(),
|
||||||
|
name: "fetch".to_string(),
|
||||||
|
}.to_rpc()).await?;
|
||||||
|
|
||||||
|
println!("Response: {:#?}", response);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@ -1,12 +1,123 @@
|
|||||||
use magnus::{function, Error, Ruby};
|
use jsonrpsee::async_client::{Client, ClientBuilder};
|
||||||
|
use tokio::process::Command;
|
||||||
|
use crate::mcp_client::McpClient;
|
||||||
|
use jsonrpsee::core::client::ClientT;
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use magnus::prelude::*;
|
||||||
|
|
||||||
fn distance(a: (f64, f64), b: (f64, f64)) -> f64 {
|
mod mcp_client;
|
||||||
((b.0 - a.0).powi(2) + (b.1 - a.1).powi(2)).sqrt()
|
mod types;
|
||||||
|
mod rpc_helpers;
|
||||||
|
mod stdio_transport;
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
hash::{Hash, Hasher},
|
||||||
|
};
|
||||||
|
|
||||||
|
use magnus::{function, method, prelude::*, scan_args::{get_kwargs, scan_args}, typed_data, Error, RHash, Ruby, Symbol, TryConvert, Value};
|
||||||
|
use serde_magnus::serialize;
|
||||||
|
use crate::types::{CallToolRequestParams, Implementation, InitializeRequestParams, InitializeResult};
|
||||||
|
|
||||||
|
// Create global runtime
|
||||||
|
static RUNTIME: Lazy<tokio::runtime::Runtime> = Lazy::new(|| {
|
||||||
|
tokio::runtime::Runtime::new().expect("Failed to create Tokio runtime")
|
||||||
|
});
|
||||||
|
|
||||||
|
#[magnus::wrap(class = "Mcp::Client", free_immediately, size)]
|
||||||
|
struct McpClientRb {
|
||||||
|
client: McpClient,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl McpClientRb {
|
||||||
|
fn new(command: String, args: Vec<String>) -> Result<Self, magnus::Error> {
|
||||||
|
let client = RUNTIME.block_on(async {
|
||||||
|
let child = Command::new(command)
|
||||||
|
.args(args)
|
||||||
|
.stdin(std::process::Stdio::piped())
|
||||||
|
.stdout(std::process::Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let transport = stdio_transport::StdioTransport::new(child);
|
||||||
|
|
||||||
|
ClientBuilder::default().build_with_tokio(
|
||||||
|
transport.clone(),
|
||||||
|
transport.clone(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(Self { client: McpClient { client } })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn connect(&self) -> Result<bool, magnus::Error> {
|
||||||
|
RUNTIME.block_on(async {
|
||||||
|
let a = self.client.initialize(InitializeRequestParams {
|
||||||
|
capabilities: Default::default(),
|
||||||
|
client_info: Implementation { name: "ABC".to_string(), version: "0.0.1".to_string() },
|
||||||
|
protocol_version: "2024-11-05".to_string(),
|
||||||
|
}).await;
|
||||||
|
|
||||||
|
match a {
|
||||||
|
Ok(_) => Ok(true),
|
||||||
|
Err(e) => Err(magnus::Error::new(
|
||||||
|
magnus::exception::runtime_error(),
|
||||||
|
e.to_string(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn list_tools(&self) -> Result<Value, magnus::Error> {
|
||||||
|
RUNTIME.block_on(async {
|
||||||
|
let a = self.client.list_tools().await;
|
||||||
|
|
||||||
|
match a {
|
||||||
|
Ok(tools) => serialize::<_, Value>(&tools),
|
||||||
|
Err(e) => Err(Error::new(
|
||||||
|
magnus::exception::runtime_error(),
|
||||||
|
e.to_string(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call_tool(&self, values: &[Value]) -> Result<Value, magnus::Error> {
|
||||||
|
let args = scan_args::<(Value,), (), (), (), RHash, ()>(values)?;
|
||||||
|
let ((name,)) = args.required;
|
||||||
|
let kwargs: RHash = args.keywords;
|
||||||
|
let kwargs: serde_json::Map<String, serde_json::Value> = serde_magnus::deserialize(kwargs)?;
|
||||||
|
|
||||||
|
let name = match Symbol::from_value(name) {
|
||||||
|
Some(symbol) => symbol.name()?.to_string(),
|
||||||
|
None => String::try_convert(name)?,
|
||||||
|
};
|
||||||
|
|
||||||
|
RUNTIME.block_on(async {
|
||||||
|
let a = self.client.call_tool::<serde_json::Value>(CallToolRequestParams {
|
||||||
|
name,
|
||||||
|
arguments: kwargs,
|
||||||
|
}).await;
|
||||||
|
|
||||||
|
match a {
|
||||||
|
Ok(a) => Ok(serde_magnus::serialize(&a)?),
|
||||||
|
Err(e) => Err(Error::new(
|
||||||
|
magnus::exception::runtime_error(),
|
||||||
|
e.to_string(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[magnus::init]
|
#[magnus::init]
|
||||||
fn init(ruby: &Ruby) -> Result<(), Error> {
|
fn init(ruby: &Ruby) -> Result<(), Error> {
|
||||||
ruby.define_global_function("distance", function!(distance, 2));
|
let module = ruby.define_module("Mcp")?;
|
||||||
|
let client_class = module.define_class("Client", ruby.class_object())?;
|
||||||
|
|
||||||
|
client_class.define_singleton_method("new", function!(McpClientRb::new, 2))?;
|
||||||
|
client_class.define_method("connect", method!(McpClientRb::connect, 0))?;
|
||||||
|
client_class.define_method("list_tools", method!(McpClientRb::list_tools, 0))?;
|
||||||
|
client_class.define_method("call_tool", method!(McpClientRb::call_tool, -1))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
37
ext/mcp/src/mcp_client.rs
Normal file
37
ext/mcp/src/mcp_client.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
use jsonrpsee::async_client::Client;
|
||||||
|
use jsonrpsee::core::client::ClientT;
|
||||||
|
use tokio::process::Child;
|
||||||
|
use stdio_transport::StdioTransport;
|
||||||
|
use crate::rpc_helpers::{NoParams, ToRpcArg};
|
||||||
|
use crate::stdio_transport;
|
||||||
|
use crate::types::{CallToolRequestParams, InitializeRequestParams, InitializeResult, ListToolsRequestParams, ListToolsResult, Tool};
|
||||||
|
|
||||||
|
pub struct McpClient {
|
||||||
|
pub(crate) client: Client,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl McpClient {
|
||||||
|
pub async fn initialize(&self, params: InitializeRequestParams) -> Result<InitializeResult, anyhow::Error> {
|
||||||
|
let result: InitializeResult = self.client.request("initialize", params.to_rpc()).await?;
|
||||||
|
self.client.notification("notifications/initialized", NoParams).await?;
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn list_tools(&self) -> Result<Vec<Tool>, anyhow::Error> {
|
||||||
|
let mut tools = vec![];
|
||||||
|
|
||||||
|
let result: ListToolsResult = self.client.request("tools/list", NoParams).await?;
|
||||||
|
tools.extend(result.tools);
|
||||||
|
|
||||||
|
while let Some(cursor) = result.next_cursor.as_ref() {
|
||||||
|
let result: ListToolsResult = self.client.request("tools/list", ListToolsRequestParams { cursor: Some(cursor.clone()) }.to_rpc()).await?;
|
||||||
|
tools.extend(result.tools);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(tools)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn call_tool<T: serde::de::DeserializeOwned>(&self, params: CallToolRequestParams) -> Result<T, anyhow::Error> {
|
||||||
|
Ok(self.client.request("tools/call", params.to_rpc()).await?)
|
||||||
|
}
|
||||||
|
}
|
||||||
31
ext/mcp/src/rpc_helpers.rs
Normal file
31
ext/mcp/src/rpc_helpers.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
use jsonrpsee::core::traits::ToRpcParams;
|
||||||
|
use serde::Serialize;
|
||||||
|
use serde_json::Error;
|
||||||
|
use serde_json::value::RawValue;
|
||||||
|
|
||||||
|
pub struct RpcArg<T>(T);
|
||||||
|
|
||||||
|
impl<T: Serialize> ToRpcParams for RpcArg<T> {
|
||||||
|
fn to_rpc_params(self) -> Result<Option<Box<RawValue>>, Error> {
|
||||||
|
let s = String::from_utf8(serde_json::to_vec(&self.0)?).expect("Valid UTF8 format");
|
||||||
|
RawValue::from_string(s).map(Some)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ToRpcArg: Sized {
|
||||||
|
fn to_rpc(self) -> RpcArg<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Serialize> ToRpcArg for &T {
|
||||||
|
fn to_rpc(self) -> RpcArg<Self> {
|
||||||
|
RpcArg(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NoParams;
|
||||||
|
|
||||||
|
impl ToRpcParams for NoParams {
|
||||||
|
fn to_rpc_params(self) -> Result<Option<Box<RawValue>>, Error> {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
48
ext/mcp/src/stdio_transport.rs
Normal file
48
ext/mcp/src/stdio_transport.rs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
use std::sync::Arc;
|
||||||
|
use tokio::process::{Child, ChildStdin, ChildStdout};
|
||||||
|
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
|
||||||
|
use jsonrpsee::core::async_trait;
|
||||||
|
use jsonrpsee::core::client::{ReceivedMessage, TransportReceiverT, TransportSenderT};
|
||||||
|
use tracing::debug;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct StdioTransport {
|
||||||
|
stdin: Arc<tokio::sync::Mutex<ChildStdin>>,
|
||||||
|
stdout: Arc<tokio::sync::Mutex<BufReader<ChildStdout>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StdioTransport {
|
||||||
|
pub fn new(mut child: Child) -> Self {
|
||||||
|
let stdin = Arc::new(tokio::sync::Mutex::new(child.stdin.take().unwrap()));
|
||||||
|
let stdout = Arc::new(tokio::sync::Mutex::new(BufReader::new(child.stdout.take().unwrap())));
|
||||||
|
Self { stdin, stdout }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl TransportSenderT for StdioTransport {
|
||||||
|
type Error = tokio::io::Error;
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(self), level = "trace")]
|
||||||
|
async fn send(&mut self, msg: String) -> Result<(), Self::Error> {
|
||||||
|
debug!("Sending: {}", msg);
|
||||||
|
let mut stdin = self.stdin.lock().await;
|
||||||
|
stdin.write_all(msg.as_bytes()).await?;
|
||||||
|
stdin.write_all(b"\n").await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl TransportReceiverT for StdioTransport {
|
||||||
|
type Error = tokio::io::Error;
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(self), level = "trace")]
|
||||||
|
async fn receive(&mut self) -> Result<ReceivedMessage, Self::Error> {
|
||||||
|
let mut stdout = self.stdout.lock().await;
|
||||||
|
let mut str = String::new();
|
||||||
|
stdout.read_line(&mut str).await?;
|
||||||
|
debug!("Received: {}", str);
|
||||||
|
Ok(ReceivedMessage::Text(str))
|
||||||
|
}
|
||||||
|
}
|
||||||
13984
ext/mcp/src/types.rs
Normal file
13984
ext/mcp/src/types.rs
Normal file
File diff suppressed because it is too large
Load Diff
27
lib/mcp.rb
27
lib/mcp.rb
@ -1,9 +1,32 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "mcp/version"
|
require_relative "mcp/version"
|
||||||
require_relative "mcp/mcp"
|
|
||||||
|
|
||||||
module Mcp
|
module Mcp
|
||||||
class Error < StandardError; end
|
class Error < StandardError; end
|
||||||
# Your code goes here...
|
|
||||||
|
class Client
|
||||||
|
def tools
|
||||||
|
ToolsProxy.new(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class ToolsProxy
|
||||||
|
def initialize(client)
|
||||||
|
@client = client
|
||||||
|
@tools = client.list_tools
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def respond_to_missing?(name, include_private = false)
|
||||||
|
@tools.any? { |tool| tool["name"] == name.to_s } || super
|
||||||
|
end
|
||||||
|
|
||||||
|
def method_missing(name, **kwargs)
|
||||||
|
@client.call_tool(name, **kwargs)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require_relative "mcp/mcp"
|
||||||
|
|||||||
@ -6,6 +6,9 @@ RSpec.describe Mcp do
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "does something useful" do
|
it "does something useful" do
|
||||||
expect(false).to eq(true)
|
a = Mcp::Client.new("/Users/joshuacoles/.local/bin/mcp-server-fetch", [])
|
||||||
|
expect(a.connect).to eq(true)
|
||||||
|
puts a.list_tools
|
||||||
|
puts a.tools.fetch(url: 'http://example.com')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user