Skip to content

chore: house keeping, more tests, improved documentation #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Apr 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# **Contributing to rust-mcp-sdk**

🎉 Thank you for your interest in improving **rust-mcp-sdk**! Every contribution, big or small, is valuable and appreciated.

## **Code of Conduct**

We follow the [Rust Code of Conduct](https://www.rust-lang.org/policies/code-of-conduct). Please be respectful and inclusive when contributing.

## **How to Contribute**

### Participating in Tests, Documentation, and Examples

We highly encourage contributors to improve test coverage, enhance documentation, and introduce new examples to ensure the reliability and usability of the project. If you notice untested code paths, missing documentation, or areas where examples could help, consider adding tests, clarifying explanations, or providing real-world usage examples. Every improvement helps make the project more robust, well-documented, and accessible to others!

### Participating in Issues

You can contribute in three key ways:

1. **Report Issues** – If you find a bug or have an idea, open an issue for discussion.
2. **Help Triage** – Provide details, test cases, or suggestions to clarify issues.
3. **Resolve Issues** – Investigate problems and submit fixes via Pull Requests (PRs).

Anyone can participate at any stage, whether it's discussing, triaging, or reviewing PRs.

### **Filing a Bug Report**

When reporting a bug, use the provided issue template and fill in as many details as possible. Don’t worry if you can’t answer everything—just provide what you can.

### **Fixing Issues**

Most issues are resolved through a Pull Request. PRs go through a review process to ensure quality and correctness.

## **Pull Requests (PRs)**

We welcome PRs! Before submitting, please:

1. **Discuss major changes** – Open an issue before adding a new feature and opening a PR.
2. **Create a feature branch** – Fork the repo and branch from `main`.
3. **Write tests** – If your change affects functionality, add relevant tests.
4. **Update documentation** – If you modify APIs, update the docs.
5. **Run tests** – Make sure all tests succeed by running:

```sh
cargo make test
```

### **Commit Best Practices**

- **Relate PR changes to the issue** – Changes in a pull request (PR) should directly address the specific issue it’s tied to. Unrelated changes should be split into separate issues and PRs to maintain focus and simplify review.
- **Logically separate commits** – Keep changes atomic and easy to review.
- **Maintain a bisect-able history** – Each commit should compile and pass all tests to enable easy debugging with `git bisect` in case of regression.

## License

By contributing to rust-mcp-sdk, you acknowledge and agree that your contributions will be licensed under the terms specified in the LICENSE file located in the root directory of this repository.

---
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,21 @@ The same principles outlined above apply to the client-side handlers, `mcp_clien
Use `client_runtime::create_client()` or `client_runtime_core::create_client()` , respectively.
Check out the corresponding examples at: [examples/simple-mcp-client](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/simple-mcp-client) and [examples/simple-mcp-client-core](https://github.com/rust-mcp-stack/rust-mcp-sdk/tree/main/examples/simple-mcp-client-core).

## Contributing

We welcome everyone who wishes to contribute! Please refer to the [contributing](CONTRIBUTING.md) guidelines for more details.

Check out our [development guide](development.md) for instructions on setting up, building, testing, formatting, and trying out example projects.

All contributions, including issues and pull requests, must follow
Rust's Code of Conduct.

Unless explicitly stated otherwise, any contribution you submit for inclusion in rust-mcp-sdk is provided under the terms of the MIT License, without any additional conditions or restrictions.

## Development

Check out our [development guide](development.md) for instructions on setting up, building, testing, formatting, and trying out example projects.

## License

This project is licensed under the MIT License. see the [LICENSE](LICENSE) file for details.
57 changes: 57 additions & 0 deletions crates/rust-mcp-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,3 +296,60 @@ pub fn derive_json_schema(input: TokenStream) -> TokenStream {
};
TokenStream::from(expanded)
}

#[cfg(test)]
mod tests {
use super::*;
use syn::parse_str;
#[test]
fn test_valid_macro_attributes() {
let input = r#"name = "test_tool", description = "A test tool.""#;
let parsed: MCPToolMacroAttributes = parse_str(input).unwrap();

assert_eq!(parsed.name.unwrap(), "test_tool");
assert_eq!(parsed.description.unwrap(), "A test tool.");
}

#[test]
fn test_missing_name() {
let input = r#"description = "Only description""#;
let result: Result<MCPToolMacroAttributes, Error> = parse_str(input);
assert!(result.is_err());
assert_eq!(
result.err().unwrap().to_string(),
"The 'name' attribute is required."
)
}

#[test]
fn test_missing_description() {
let input = r#"name = "OnlyName""#;
let result: Result<MCPToolMacroAttributes, Error> = parse_str(input);
assert!(result.is_err());
assert_eq!(
result.err().unwrap().to_string(),
"The 'description' attribute is required."
)
}

#[test]
fn test_empty_name_field() {
let input = r#"name = "", description = "something""#;
let result: Result<MCPToolMacroAttributes, Error> = parse_str(input);
assert!(result.is_err());
assert_eq!(
result.err().unwrap().to_string(),
"The 'name' attribute should not be an empty string."
);
}
#[test]
fn test_empty_description_field() {
let input = r#"name = "my-tool", description = """#;
let result: Result<MCPToolMacroAttributes, Error> = parse_str(input);
assert!(result.is_err());
assert_eq!(
result.err().unwrap().to_string(),
"The 'description' attribute should not be an empty string."
);
}
}
Loading