Repository navigation
Extract the MCP client, registry, and audit log into this workspace - #1
Merged
Merged
Conversation
…data Renames the `template` crate to `tinymcp` and updates its description, keywords, and categories to reflect the actual Model Context Protocol functionality. Also corrects the `tinymcp-bus` description and keywords to reference the proper module name instead of the placeholder "template". Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Introduce a new specification document for the MCP extraction process, defining the protocol and data format requirements for extracting metadata from MCP-compliant sources. This provides a formal reference for implementation and ensures consistent behavior across tools. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a new document outlining the plan for extracting the Model Context Protocol (MCP) implementation into a standalone library, providing a clear reference for the upcoming refactoring work. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Added a guard clause to prevent a panic when the sanitizer receives an empty or malformed input that previously bypassed the initial length check. This ensures the function returns a safe default instead of crashing, improving robustness against unexpected data from external sources. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a new test module to verify the sanitization behavior in the tinymcp-bus crate, ensuring input is properly cleaned before processing. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Make the sanitize module publicly accessible from the bus crate so that consumers can use its sanitization utilities directly. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Adds a test module to the sanitize module in tinymcp-bus, providing initial test coverage for the sanitization logic. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Reordered imports across several files to follow a consistent convention of grouping external crate imports before internal ones, and added public re-exports of the sanitize module's constants and functions from the tinymcp-bus crate root so that callers can access them without descending into the module hierarchy. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
…t explanation Backtick-quote `OpenHuman` in the module-level doc comment to match the code-style convention used elsewhere. Reword the test comment to explain that a lowercased-copy offset is shifted in the original, rather than describing the consequence as landing mid-codepoint, making the reason for scanning original bytes clearer. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Removed the `ConfigValue` enum and its associated `Display` implementation from the configuration types module, as they were no longer referenced anywhere in the codebase. This cleanup reduces dead code and simplifies the module. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Removed the unused `std::io::Error` import from the config module to clean up the code and eliminate a compiler warning. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
When the configuration file does not exist, the parser now returns a default configuration instead of failing with an error. This allows the application to start with sensible defaults when no user configuration is present. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
…erivation Add the `schemars` crate as an optional dependency behind a new `schemars` feature flag, enabling hosts to generate JSON Schema from the bus's configuration payloads for building settings user interfaces. The feature is off by default to avoid paying the compile cost when only making calls. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Update the schemars dependency to version 1.2.2, which includes breaking changes requiring a new ref-cast dependency and an upgrade to syn 3.0.3 for its derive macros. This change keeps the dependency current and ensures compatibility with the latest crate ecosystem. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add `#![allow(...)]` attributes to two test modules so that clippy does not flag the deliberate use of `unwrap`, `expect`, and `panic` in test code, keeping the test output clean without changing any test logic. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The transport layer now correctly processes messages with zero payload length instead of treating them as invalid. This change ensures compatibility with clients that send empty messages for keep-alive or protocol negotiation purposes. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Remove the `serde(rename_all = "camelCase")` attribute from `McpRemoteTool` to let field names serialize as-is, and replace the convoluted `is_error` expression in `McpToolResult::success` with a direct `false` value for clarity. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The transport layer now correctly processes messages with zero payload length, which previously caused an error when attempting to read from an empty buffer. This fix ensures that zero-length messages are accepted as valid inputs rather than being rejected. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The test for connection timeout was using an incorrect assertion that would pass even when the timeout did not occur. The assertion has been updated to properly verify that the connection attempt times out as expected. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The transport module and its public types are now re-exported from the crate root, making them available to downstream consumers. Test assertions in the transport test file are reformatted for improved readability without changing any behavior. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
…rtion in test Backtick-quote `OpenID` in the doc comment for `AuthorizationServerMetadata` to follow Rust documentation conventions for protocol names. Replace a runtime assertion with a `const` assertion in the display title test to catch violations at compile time rather than at test time. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Mark the sanitize module and contract crate config/transport types as done, and add a note about the proxy field replacement rationale. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Spec and plan for moving OpenHuman's MCP client, registry and audit log into this repository, plus the first two phases of the port: - sanitize/ moves into the contract crate, where both the transports and a host can name one copy of the stripping rule. - config/ and transport/ carry the payload types, each with a unit test pinning its wire form. - The protocol-version constants are hoisted out of the two transports that duplicated them. The fence scan now runs over the original bytes instead of a lowercased copy. Lowercasing is not length-preserving in Unicode, so the old offset could land mid-codepoint: a tool description containing U+0130 before a fence token either corrupted the string or panicked outright. Tool descriptions come from whatever server the user installed, so that abort was reachable from outside. Both cases are regression-tested. Co-authored-by: Medulla <medulla@tinyhumans.ai>
When a service attempts to register with an ID that already exists in the registry, the system now returns an error instead of silently overwriting the existing entry. This prevents accidental replacement of active services and makes the registration contract explicit. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
When a client attempts to register a capability that already exists in the registry, the system now returns the existing entry instead of failing with an error. This makes registration idempotent and avoids unnecessary disruptions when clients reconnect or re-register the same capability. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Changed the test assertion to expect an empty vector instead of a single-element vector when no topics match the filter, ensuring the test correctly validates the registry's filtering behavior. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Make the registry module and its types publicly available from the crate root by adding the module declaration and re-exporting all public types. This allows consumers to use registry-related types without importing the internal module path. Additionally, reformat several test assertions to improve readability by breaking long lines and adjusting indentation. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
…cp-bus Remove the `#[non_exhaustive]` attribute from every public struct across the config, registry, and transport type modules. This change allows downstream consumers to construct these structs directly with struct literal syntax, which is necessary for ergonomic testing and for hosts that need to build these types without going through a builder or constructor. The attribute was originally added to reserve the right to add fields in future versions, but the current development velocity and the fact that these types are already versioned through the crate's own semver make the restriction more costly than the flexibility it protects. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Replace the existing test that treated a banner line as a non-JSON reply with a test that verifies banner lines are skipped during handshake. Add two new tests: one for a line that looks like JSON but is not a valid reply, and one for a reply that lacks both a result and an error field. These changes improve error reporting and make the transport more resilient to common server misconfigurations. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
…l bus Add three integration tests that exercise the module's setup function against a real in-memory bus, covering the nominal case where the module comes up and serves its interface, the end-to-end call path through the bus, and the failure case where a corrupted store prevents the module from starting. Also re-export the setup function under a test-only alias so the test module can call it without making it part of the public API. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The `setup` function visibility is changed from private to `pub(super)` so that tests in the sibling test module can call it directly, removing the need for a separate `setup_for_test` re-export. The test calls are updated to use `super::setup` instead of the removed alias, and the call arguments are now properly converted with `try_into` to match the expected types. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The serving connection was being dropped before the call, releasing both the bus name and the served object. The test now holds a clone of the connection for its duration to prevent premature cleanup. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
…n behaviour Add three new test cases covering the supervisor's ability to handle transient store read failures, detect and reconnect dropped transports, and apply exponential backoff when a server cannot be reached. These scenarios ensure the supervisor loop remains robust under real-world conditions rather than panicking or retrying endlessly. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Adds two tests to the audit store test suite. The first verifies that a limit value exceeding the column's storage capacity is rejected, complementing the existing offset bound test. The second ensures that reading a row with an unreadable argument summary fails, as the column contains JSON and an undecodable value represents corruption that should not silently produce an empty summary. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The limit parameter in the audit log query is now capped at the maximum page size instead of being refused when it exceeds the column's capacity. This ensures that a caller requesting an unreasonably large limit receives the largest possible page rather than an error, making the API more resilient to clumsy requests. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
…onnection Adds thirteen integration tests covering the remaining public API paths through the registry facade, including credential merging on reinstall, source-routed name stripping, disconnected credential updates, OAuth completion failure handling, and subprocess connection testing. These tests ensure the facade correctly handles edge cases that were previously untested. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The test for the facade handing out pieces now exercises the vault's request and submit flow before asserting on pending counts, ensuring the vault interaction path is covered alongside the existing oauth and overview assertions. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The test for a non-existent command now checks that the error message contains "npx" and explicitly excludes transport or HTTP errors, making the assertion more precise about which execution arm produced the failure. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Reformat test assertions and function calls across multiple test files to follow a consistent style, wrapping long lines and breaking chained method calls onto separate lines where they exceed the project's line-length limit. Also reorder import statements in `config_servers/test.rs`, `oauth/mod.rs`, and `tinybus_module/test.rs` to match the project's convention of grouping standard library imports before external crate imports. These changes are purely cosmetic and do not alter any runtime behaviour. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
… write! Reorder the `mcp_endpoint` and `handle` functions in the config servers test so that `handle` is defined before `mcp_endpoint`, which reads more naturally. In the registry connections test, replace `format!` with `write!` to avoid unnecessary string allocations when building shell script bodies. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Replaced `write!` with `writeln!` in test helper functions to ensure each shell command ends with a proper newline, and corrected indentation in the `mcp_endpoint` helper to use consistent spacing. These changes fix subtle issues where missing newlines could cause the generated shell scripts to behave incorrectly during test execution. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The unix stdio test module was using `write!` without importing the `fmt::Write` trait, which caused a compilation error on unix platforms. The import is now added to ensure the tests compile correctly. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
…er function The inline route handlers for `/register` and `/token` in the test authority have been moved into a separate `endpoints()` function. This keeps the router builder readable by avoiding a single expression that spans the entire function length. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Moves the `handle` function from inside `mcp_server` to a standalone item, and changes `list_body` to accept a slice instead of an owned vector. This reduces nesting and avoids unnecessary allocations without altering test behaviour. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
…rotocol version The `envelope()` helper function was moved from inside the `catalog` test helper to module level so it can be reused by other tests. In the stdio transport test, the `LATEST_PROTOCOL_VERSION` constant is now interpolated directly into the format string instead of being passed as an argument, making the shell script template more readable. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Co-authored-by: Medulla <medulla@tinyhumans.ai>
…elper Extract the nvm directory resolution into its own function so that the version comparison logic can be tested against a synthetic directory tree rather than depending on the developer's or CI runner's actual nvm installation. Add seven tests covering version ordering, non-version directories, missing bin directories, empty layouts, absent directories, and environment variable override. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add two tests that verify write failures are reported with actionable wording: a broken pipe is described as the server having closed its output, while other errors include what operation was being attempted. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
… ETXTBSY race Replace the `script` helper that writes an executable shell script to disk with a `shell_client` function that passes the script body as an argument to `/bin/sh -c`. The old approach created a race condition: when tests run in parallel, one test's fork and exec can collide with another test's still-open file descriptor, causing the kernel to refuse execution with `ETXTBSY`. Using the interpreter directly eliminates the written file and therefore the race entirely. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Reformat the `shell_client` helper function signature and its call sites to improve readability by breaking long parameter lists across multiple lines. In the `a_reply_carrying_neither_a_result_nor_an_error_is_reported` test, replace the separate script path creation and `McpStdioClient::new` call with a direct `shell_client` invocation, simplifying the test setup while preserving the same behavior. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
… commands The test helper `write_script` created an executable shell script on disk and passed its path as the server command. This caused `ETXTBSY` failures under parallel test execution because one test's still-open file descriptor prevented another test's `exec` from running the same script. The change removes `write_script` and instead passes the script body directly as an argument to `/bin/sh -c`, eliminating the race condition since the interpreter is never written by the test. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Several test functions in the stdio transport test module were creating a temporary directory via `tempfile::tempdir().unwrap()` but never using the resulting directory handle. These unused allocations have been removed to clean up the test code and eliminate unnecessary filesystem operations during test execution. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
Changed the `shell_client` call in the test to pass `body` by value instead of by reference, since the function takes ownership of the string. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The test helper that wrote executable shell scripts to disk and returned their paths has been removed. Instead, each test now passes the script body directly as an argument to `/bin/sh -c`. This eliminates a race condition where the kernel refused to exec a script file with `ETXTBSY` when another test still held the file descriptor open, since the suite runs test cases in parallel. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The test helper `responder` no longer requires a temporary directory, so the unnecessary `tempfile::tempdir()` calls and the conversion of its return value to a string have been removed throughout the test module. This simplifies the test setup and eliminates a source of potential test noise from leftover temp directories. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
The temporary directory variable was declared but never used in the test, causing a compiler warning. Removing it cleans up the test without affecting its behavior. Auto-committed-on: dragonfly Co-authored-by: Medulla <medulla@tinyhumans.ai>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Extracts OpenHuman's MCP client, server registry, and write-audit log into this
workspace as a reusable TinyBus module, and hardens it on the way over.
What changed
crates/tinymcp-busholds the wire contract — payload types, member names, andthe sanitizer — with no transport, no runtime, and no behavior.
crates/tinymcpholds everything that answers a frame: both MCP transports (Streamable HTTP with
OAuth discovery and SSE, and stdio JSON-RPC), the server registry over SQLite,
the Smithery and official catalogs, the connection supervisor, the browser
sign-in flow, the setup secret vault, and the write-audit log. It re-exports the
whole contract, so
tinymcp::McpToolandtinymcp_bus::McpToolare the sametype rather than structural twins.
The 28-member TinyBus interface is behind a default-on
modulefeature, so ahost consuming this by path dependency does not pull in a second copy of
TinyBus.
Behavior changes
Nothing that crosses the RPC surface. Within this crate, three error variants
now say something more useful than what they replaced — see the defects below.
State that used to live in process-wide
OnceLocks is owned instead: theconnection map, the failure map, the pending-authorization map, the cursor
cache, the secret vault, and the registry credentials are all fields now. Two
hosts in one process no longer share connections, and the suite is no longer
order-dependent.
Defects found and fixed
Each has a regression test.
strip_instruction_fences.The scan took an offset from a lowercased copy and spliced it into the
original, so any non-ASCII character whose lowercase form has a different
UTF-8 length shifted every subsequent offset.
"İİİ<system>payload"silentlyproduced
"İİİ<syload";"İ<system>é"panicked on a non-character-boundarysplit. Tool descriptions come from user-installed servers, so this was
reachable by a third party. Now an ASCII-case-insensitive scan over the
original bytes.
reqwest::Error'sDisplayrendersthe full request URL including any
?api_key=…, which defeated the endpointredaction the error type was applying. Every reqwest cause is now stored
.without_url()..expect("reqwest client must build"). Building is fallible now, and anunusable individual proxy URL is logged and skipped rather than taking the
process down.
kill_on_drop(true).did.
original's own comment described a recheck that was never written.
SecretRef::parsestripped the scheme before trimming, so a ref withsurrounding whitespace was rejected.
Error::Unauthorizedhad dropped(HTTP 401)from its message, which iswhat OpenHuman's error classifier anchors on to demote a re-authentication
prompt out of error reporting.
MalformedResponse, which means thepeer misbehaved. It has
Error::ServerDisablednow.UnknownServer, sending auser to reinstall something they already had.
Error::NotConnectedisdistinct because the two ask different things of a caller.
On-disk compatibility
The registry file is not migrated on the way over: an installed server is state
a user set up, and losing it means re-authorizing every integration by hand.
crates/tinymcp/tests/opens_an_existing_openhuman_database.rsbuilds a databasefrom OpenHuman's original schema — copied verbatim from its history rather
than derived from this crate's, which is the point — including a row predating
the
transport,deployment_url, andenabledcolumns, and asserts the sameservers and credentials read back.
The audit log moves to its own file,
mcp_audit/mcp_audit.db. Rows written intoOpenHuman's memory-tree database before the move stay where they are; an audit
log is history rather than operational state, and nothing reads the old table.
Validation
All run from the repository root:
cargo fmt --all -- --check— cleancargo clippy --all-targets --all-features -- -D warnings— cleancargo build --all-targets --all-features— cleancargo test --all-features— 622 passed, 0 failedcargo run -p tinymcp --example verify_module -- target/debug/libtinymcp.so—verified, 28 members on
ai.tinyhumans.tinymcp.McpConsumed end-to-end from OpenHuman on a matching branch: its
--lib mcpsuite(192) and all four MCP integration binaries (24) pass against this crate.
Deliberately untested
The live catalog paths against Smithery and the official registry, which need
network and credentials.