Repository navigation
feat: normalize string-encoded tool arguments; move MCP server, config doc and registry tool specs into tinymcp - #30
Conversation
The agent_tools module is now declared as public in the library root, making its types and functions available to external consumers of the crate. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add the sha2 crate as a workspace dependency to support generating SHA-256 digests from a server identifier and tool name, ensuring that action tool names remain unique across different servers and after truncation. The digest becomes part of the tool name, which serves as transcript identity, and this change is purely in Rust with no transport implications. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
Replaced a direct import of `Version` with a grouped import from the parent module, aligning the test file with the project's coding conventions for clarity and maintainability. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
The version comparison logic now correctly handles pre-release identifiers by comparing them as strings when they are not purely numeric, ensuring that versions like "1.0.0-alpha" and "1.0.0-beta" are ordered properly according to semver specification. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a README file for the tinymcp-bus crate and include module-level documentation in lib.rs. This provides users with an overview of the crate's purpose and usage, improving discoverability and onboarding for new contributors. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
Changed the test assertion to match the actual return type of the tool call, which returns a `ToolResult` containing a `ContentItem` rather than a plain string. This fixes a failing test caused by an incorrect expected value. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
The test module in the registry ops module was failing to compile because it referenced the `error` module from `tinymcp`, which was not imported. Added the necessary use statement to resolve the compilation error. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
The `tool_call` method now passes arguments through `normalize_tool_arguments`, which accepts `null` as an empty object and decodes a JSON-encoded string into an object, preventing servers from rejecting malformed input. A new `InvalidArguments` error variant is returned when the arguments are neither an object nor a string containing one, and the test suite covers this case. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
Introduce a config document module that provides structured documentation for tool configuration, including types for document entries and a document builder. This enables tools to declare their configuration schema in a standardized way, improving discoverability and validation of tool parameters. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a new `Error::ConfigDoc` variant that carries a plain detail string, rendered without any prefix so it can be shown directly beside the user's text in an editor. This allows validation of `mcp.json` documents to produce clear, context-specific refusal messages that name the entry and field, rather than generic error text. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
Replaced a match statement with a more concise if-let pattern when checking the transport type in the config document renderer, and updated a test assertion to use `from_ref` instead of cloning a server ID. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
Updated the test to verify the correct supervisor state after initialization, ensuring the assertion matches the expected default configuration rather than an incorrect previous value. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
…exports The supervisor module was using incorrect type paths for `SupervisorId` and `SupervisorState`, causing compilation errors. Updated the type references to use the correct `types` submodule paths and added the missing `supervisor` module re-export in the registry's `mod.rs`. Also fixed the `test.rs` transport file to use the proper import path for `SupervisorId`. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
…/src/transport/mod.rs,crates/ti Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
The `server` module is now declared as `pub mod server` in the library root, making it accessible to external consumers of the crate. This change was needed to allow users to interact with the server functionality from outside the crate. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
The `HashMap` import in the server types module was unused and caused a compiler warning. Removing it cleans up the code and eliminates unnecessary noise during builds. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
The server now clones the state for each request handler invocation instead of sharing a single mutable reference, preventing race conditions when multiple requests arrive simultaneously. This change ensures that concurrent requests do not interfere with each other's state modifications. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
The `args` module was previously private, making it inaccessible to external consumers of the crate. This change makes it public so that callers can access argument parsing utilities provided by the server. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
The `args` module in the server crate was no longer referenced anywhere in the codebase, so it has been removed to eliminate dead code and reduce compilation overhead. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
The session module and its ClientSession type are now publicly accessible from the server crate, allowing external consumers to interact with client sessions directly. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
The session module now uses an `Arc<RwLock<SessionState>>` to allow safe concurrent access across multiple connections. This change prevents data races and ensures consistent session state when handling simultaneous requests. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
…src/server/fixture/mod.rs,crate Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
Changed the expected JSON string in the `resources_read_answers_the_handler_contents` test from a regular string to a raw string literal to prevent potential escape sequence conflicts with the JSON content. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
When the server receives a JSON-RPC request with an empty body, it now returns a proper error response instead of panicking or hanging. This improves robustness against malformed or incomplete client messages. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
…nction Removed the dependency on `object_keys` from the session module and introduced a new `sorted_keys` helper that sorts the keys of a JSON object map. This change reduces coupling between protocol and session modules while preserving the same behaviour of producing a sorted key list for tool call logging. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
The `is_error` value is now computed before the `tracing::debug!` macro invocation to avoid a name shadowing issue where `tracing`'s own `Value` trait conflicts with the `Value` type used in the expression. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
…src/server/mod.rs,crates/tinymc Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a newline-delimited JSON-RPC transport over stdio for the MCP server, along with two new error variants to report server I/O and binding failures. The transport reads one request per line from the reader, skips blank lines, writes one response line per answer, and runs until the request stream ends. This enables the server to communicate with clients over standard input and output. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add the `server-http` feature flag to `tinymcp`, gated behind optional dependencies on `axum` and `tokio-stream`. The workspace `Cargo.toml` now declares `tokio-stream` as a shared dependency with only the `sync` feature enabled, and the `axum` entry is refactored to use minimal default features so that hosts not using the HTTP server do not link an unnecessary server stack. The test-only `axum` dependency in `crates/tinymcp/Cargo.toml` gains the `form` feature for the OAuth token endpoint used in the authorization-flow test suite. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add the HTTP server module behind the `server-http` feature flag, re-exporting `HttpServerConfig`, `run_http`, and `run_http_reporting` from the server module. This allows the HTTP server functionality to be compiled only when the feature is enabled, keeping the default build lean. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a `server_io` constructor to the `Error` enum so that callers can create `ServerIo` errors without directly accessing the internal `Box` field. This replaces a private helper function in the stdio server module, making the error construction consistent and reusable across the codebase. The test assertion is also updated to use the correct field path for accessing tool call results. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
When a POST request arrives without a Content-Type header, the server now returns a 415 Unsupported Media Type error instead of panicking. This ensures graceful handling of malformed requests and aligns with HTTP semantics. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
The SSE assertion in `get_streams_only_this_sessions_events_as_sse` was updated to expect fields in the order set by the transport (data before event), matching the actual framing behavior. A new test verifies that session IDs are redacted to a short SHA-256 digest, ensuring sensitive identifiers are not exposed in logs. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
… root Re-export the server module's public types and the HTTP transport functions from the library's top level, so that consumers can use them without navigating into the server submodule. This makes the crate's public API more discoverable and consistent with the existing re-exports for the registry and transport modules. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
…er.md Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
Reformatted long function calls and expressions across multiple files to improve readability, and updated the MCP server specification document with status, goals, acceptance criteria, and open questions sections. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
…extract envelope helper Changed the session validation function from returning `Result<(), Response>` to returning `Option<Response>`, making the happy path return `None` instead of `Ok(())` for clearer intent. Extracted a shared `envelope` helper to construct JSON-RPC 2.0 responses, eliminating duplicated `json!` macro calls in `success_response` and `error_response`. Updated `parse_tool_call_params` to take a reference instead of an owned `Value`, and switched `redact_session_id` to use `write!` for more idiomatic string building. Also corrected doc comments to properly backtick-quote `OpenHuman` as code. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a test that verifies object_keys returns keys in sorted order for JSON objects and returns an empty list for non-object values like null and arrays, ensuring the function behaves correctly across different input types. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
…alize Co-authored-by: Medulla <medulla@tinyhumans.ai>
Introduce a new agent_tools module that provides action execution capabilities for the tinymcp-bus crate. This change adds the core action types, module structure, and initial test coverage to enable agent-driven tool interactions within the bus system. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
…ences The `sha2` crate was no longer used by any code in the crate, so the dependency has been removed from `Cargo.lock` and the README has been updated to reflect the current two-dependency set. A stale doc comment referencing `action_tool_specs` and an unused import in the test module have also been cleaned up. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add two tests that verify how the tool layer handles argument encoding before passing them to the server. The first test ensures that string-encoded JSON objects and null values are normalized to proper JSON objects, while the second test confirms that non-object arguments like arrays are rejected before reaching the server. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
The Recording tool's McpToolResult now includes the markdown_formatted field, setting it to None to align with the expected structure of tool results and ensure consistency across all tool invocations. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
MCP requires arguments to be a JSON object, but some providers send JSON-encoded strings or omit the value entirely. This change normalizes the arguments using the existing `normalize_tool_arguments` function, returning a clear error message when the input cannot be converted to an object, preventing the server from receiving malformed data. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
The import of `sanitize_for_llm` was moved before the grouped import of `McpTool` and `normalize_tool_arguments` to maintain a consistent ordering of external crate imports. Auto-committed-on: macbook Co-authored-by: Medulla <medulla@tinyhumans.ai>
|
Warning Review limit reached
This review includes 49 billable files and costs up to $12.25. Or wait 33 minutes for your next included review. View limit detailsLimit details: You’ve used the included review currently available. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (49)
Comment |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Tiny Sweeper review
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 66ac4d64fe
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let row = to_installed(entry, server_id.clone(), existing.installed_at); | ||
| store.insert_server(&row)?; | ||
| write_credentials(store, &server_id, &stored)?; |
There was a problem hiding this comment.
Clear credentials when switching transport kinds
When an existing entry changes from a command to a URL (or vice versa), this rewrite restores every credential from the old transport before merging the new block. On the next connection, a former stdio environment value such as API_KEY is therefore interpreted by build_http_auth as an HTTP header and sent to the newly configured remote endpoint, potentially disclosing a secret; credentials should not carry across a stdio/HTTP transition unless explicitly redeclared.
Useful? React with 👍 / 👎.
| /// The wire contract version this crate defines. | ||
| pub const CONTRACT_VERSION: (u32, u32) = (1, 0); | ||
| /// | ||
| /// 1.1 added the [`crate::agent_tools`] family. | ||
| pub const CONTRACT_VERSION: (u32, u32) = (1, 1); |
There was a problem hiding this comment.
Keep 1.0 modules compatible with host-only additions
Adding agent_tools does not add a TinyBus member or change any serialized method payload, yet this bump makes is_compatible((1, 0)) false. A host rebuilt with this crate will consequently refuse an already deployed 1.0 module even though all module calls it can make remain wire-compatible; leave the wire-contract version unchanged for this host-side vocabulary addition.
Useful? React with 👍 / 👎.
| pub use tinymcp_bus::{ | ||
| AuthorizationServerMetadata, CONTRACT_VERSION, ChatTurn, CommandKind, ConnStatus, | ||
| ConnectedServerOverview, DEFAULT_LIST_LIMIT, ERROR_MESSAGE_MAX_BYTES, ExtraFields, HttpHeader, | ||
| INTERFACE, InstalledServer, LATEST_PROTOCOL_VERSION, MAX_DESCRIPTION_BYTES, MAX_LIST_LIMIT, | ||
| MAX_TITLE_BYTES, METHODS, McpAuthChallenge, McpAuthConfig, McpAuthHint, | ||
| McpAuthorizationContext, McpClientConfig, McpClientIdentityConfig, McpClientInfo, | ||
| McpInitializeResult, McpProxyConfig, McpRegistryAuthConfig, McpRemoteTool, McpServerConfig, | ||
| McpServerToolResult, McpSseEvent, McpTool, McpToolContent, McpToolResult, McpWriteListQuery, | ||
| McpWriteRecord, NewMcpWriteRecord, OBJECT_PATH, ProtectedResourceMetadata, RegistryConnection, | ||
| RegistryListResponse, RegistryPagination, RegistryServerDetail, RegistryServerSummary, | ||
| SUPPORTED_PROTOCOL_VERSIONS, ServerStatus, Transport, config, is_compatible, names, sanitize, | ||
| version, | ||
| ConnectedServerOverview, DEFAULT_LIST_LIMIT, ERROR_MESSAGE_MAX_BYTES, ExtraFields, | ||
| HEADER_PROTOCOL_VERSION, HEADER_SESSION_ID, HttpHeader, INTERFACE, InstalledServer, | ||
| LATEST_PROTOCOL_VERSION, MAX_DESCRIPTION_BYTES, MAX_LIST_LIMIT, MAX_TITLE_BYTES, METHODS, |
There was a problem hiding this comment.
Re-export the new agent-tool contract from tinymcp
The bus crate now exposes AgentToolSpec, AgentToolEffect, RegistryTool, ArgsError, and the associated functions, but this centralized re-export list omits all of them. Downstream users taking the implementation crate therefore cannot use the promised tinymcp::AgentToolSpec-style surface and must add or name tinymcp_bus directly, contrary to the workspace's load-bearing requirement that tinymcp re-export the contract crate's public items.
AGENTS.md reference: AGENTS.md:L79-L83
Useful? React with 👍 / 👎.
Why
An OpenHuman user asked the agent to organize their TickTick. The model (DeepSeek v4 Flash via OpenRouter) called
mcp_registry_tool_callwith"arguments": "{}": the arguments object was sent as a JSON-encoded string. Every call path forwarded that string as-is, so all four batched calls failed validation and the turn was abandoned.The fix belongs where the call is made. This PR also moves the MCP code in OpenHuman that isn't host policy into tinymcp. The companion OpenHuman PR makes it consume these pieces.
What changes
Argument normalization, in the contract (
tinymcp-bus::agent_tools)normalize_tool_argumentsreads arguments as follows:nullbecomes{}```jsonfenceMcpRegistry::tool_call(via the newError::InvalidArguments),tools/callin the server protocol, andMcpServerTool::executein the feat(tools): expose server tools as tinytools with a persistent tool cache #27toolsadapter.Registry agent tool specs (
tinymcp-bus::agent_tools)AgentToolSpec,AgentToolEffect,RegistryToolandregistry_tool_specs()describe the 9mcp_registry_*tools a host shows a model.CONTRACT_VERSIONgoes from 1.0 to 1.1.tinymcp::tools. An earlier copy of action-tool naming in the contract was removed when mergingmain.mcp.jsondocument (registry::config_doc)McpRegistry::render_config_docandMcpRegistry::apply_config_doc→ConfigApplyReport, with fieldsinstalled,updated,removedandconnect_queued.Supervisor
Supervisor::run_many, a multi-host loop that keeps one supervisor per host across ticks. It replaces a duplicate loop in OpenHuman.MCP server (
server/)clientInfosessions, stdio (run_stdio), and Streamable HTTP/SSE (run_http).McpServerHandler. It uses boxed futures and needs no newasync-traituse.server-httpfeature (axum,tokio-stream) is off by default.docs/specs/mcp-server.md.Compatibility
sha2dependency added earlier on this branch was removed again.Verification
cargo fmt --all --check: clean.cargo clippy --workspace --all-targets --all-features -- -D warnings: clean.cargo test --all-features: all pass (801 lib tests plus integration and doc tests).cargo test(default features): all pass..github/scripts/check-file-coverage.sh 90: passes; every file is at 90% or above.tools::test::string_encoded_arguments_reach_the_server_as_an_objectandarguments_that_are_not_an_object_are_refused_before_the_call. Both failed before the fix.tool_calland servertools/callequivalents.Companion PR: tinyhumansai/openhuman#6769