-
Notifications
You must be signed in to change notification settings - Fork 8
core/client: add MCP client with sessions, server requests, and docs #133
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
Draft
laulauland
wants to merge
16
commits into
main
Choose a base branch
from
mcp-client-implementation
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Conversation
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
🦋 Changeset detectedLatest commit: 37b8c04 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
4792449 to
f855e96
Compare
commit: |
f8866c3 to
4626cb6
Compare
Add complete MCP client implementation: Core Foundation: - McpClient class with fluent API (.use, .onError) - Connection class for server interactions (tools, prompts, resources) - StreamableHttpClientTransport for HTTP communication - ToolAdapter interface for SDK integration - Full TypeScript support with proper type inference - Zero runtime dependencies (built on Fetch API) Session Management: - ClientSessionAdapter interface for session persistence - InMemoryClientSessionAdapter implementation - openSessionStream() for GET SSE streams - Session lifecycle management (create, reconnect, delete) - Event replay with Last-Event-ID support Server-Initiated Requests: - onSample() and onElicit() handler registration - Client _dispatch() method for processing server requests - Middleware support for server-initiated requests - Automatic SSE stream processing for incoming requests - Response sending back to server via POST Testing and Documentation: - 182 integration tests (stateless, session, server requests, E2E) - 624 expect() assertions validating all features - Multi-server workflow tests - Progress notification handling - Error recovery patterns - Complete README documentation with examples The client mirrors McpServer patterns but inverted for sending requests rather than handling them. Supports stateless operations by default with opt-in session and bidirectional features.
Make openSessionStream() return Promise<void> instead of returning a stream. This removes the complexity of tee'ing streams and race conditions entirely. The connection processes SSE events internally for server-initiated requests (elicitation/sampling). Tests that need to observe raw events use the test-utils openSessionStream() helper directly. This is cleaner architecture because: - No stream tee complexity - No race conditions - Aligns with actual usage (users just call openSessionStream(), don't need the stream) - Server only allows one SSE stream per session anyway Breaking change: openSessionStream() now returns void Tests updated to use test-utils helper for event observation
CI shows timing issue where ping event not received before making fetch call. Add small 50ms delay to ensure SSE stream is fully connected and ping event has been delivered before making tool call. Fixes intermittent CI failure: Expected length 4, Received length 3
The test was expecting 4 events (ping + 3 progress) but ping delivery is inconsistent in CI. Changed to collect events with 1000ms timeout and filter for progress notifications, making the test robust regardless of whether ping arrives or not. This fixes the intermittent CI failure where only 3 events were received.
Add 'headers' option to StreamableHttpClientTransportOptions to support
custom headers in all HTTP requests. This enables:
- Authorization tokens (Bearer, API keys, etc.)
- Custom authentication schemes
- Request tracking headers
- Any other custom HTTP headers
Changes:
- Add headers option to StreamableHttpClientTransportOptions
- Store custom headers in transport and pass to Connection
- Merge custom headers into all fetch calls:
* Initialize request
* Connection requests (tools, prompts, resources)
* SSE stream opening
* Response sending back to server
- Custom headers override protocol defaults if conflicts exist
- Add comprehensive tests for custom headers functionality
Usage example:
```typescript
const transport = new StreamableHttpClientTransport({
headers: {
'Authorization': 'Bearer my-token',
'X-API-Key': 'my-key'
}
});
```
Note: This complements the OAuth support. OAuth provides automatic
token management, while custom headers allow manual control and
support for non-OAuth auth schemes.
…construction
Headers are now passed per-connection rather than per-transport.
This allows using the same transport instance to connect to multiple
servers with different authentication headers.
Before:
const transport = new StreamableHttpClientTransport({
headers: { Authorization: 'Bearer token' }
});
const connection = await connect(serverUrl);
After:
const transport = new StreamableHttpClientTransport();
const connection = await connect(serverUrl, {
headers: { Authorization: 'Bearer token' }
});
This is more flexible for multi-server scenarios where each server
needs different headers.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
Added comprehensive documentation for the custom headers feature: - New section: 'Connection with Custom Headers' - Updated 'Multiple Server Connections' section with header examples - Added to features list - Explained header behavior and OAuth interaction Shows how to: - Pass headers at connect() time - Use different headers for different servers - Understand header precedence with OAuth 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
d68a251 to
72b92c3
Compare
Problem: - mcp-lite was incorrectly appending /.well-known/oauth-protected-resource to the full MCP endpoint URL - Example: https://example.com/mcp → https://example.com/mcp/.well-known/oauth-protected-resource (wrong) - RFC 8707 Section 3 requires .well-known endpoints at the origin, not sub-paths Solution: - Extract origin from baseUrl for RFC 8707 compliant discovery - Correct: https://example.com/mcp → https://example.com/.well-known/oauth-protected-resource - Added WWW-Authenticate header fallback for servers that provide as_uri hint - Added validateAndReturnEndpoints() helper to reduce code duplication Testing: - Added 3 new integration tests covering origin-based discovery, WWW-Authenticate fallback, and graceful failure scenarios - All 14 OAuth tests pass - Full test suite passes (234 tests)
Adds automatic client registration for OAuth-protected MCP servers that don't require pre-configured client credentials. Changes: - Add registerOAuthClient() function implementing RFC 7591 - Extend OAuthAdapter with client credential storage - Update OAuthConfig to make clientId optional - Automatically perform DCR when no clientId is provided - Store and reuse registered client credentials per authorization server - Add registrationEndpoint to OAuthEndpoints from discovery - Remove dynamic imports from transport-http.ts Implementation: - Client credentials are stored per authorization server URL - Reuses existing credentials if already registered - Falls back to error if DCR not available and no clientId - Stores clientId in PendingAuthState for token operations Testing: - All 234 tests pass including OAuth integration tests - TypeScript compilation passes without errors
… README Updates client documentation with: - DCR support (clientId is now optional) - Automatic client registration via RFC 7591 - Origin-based OAuth discovery per RFC 8707 Section 3 - Client credential storage methods in OAuthAdapter - Examples of manual DCR usage - Updated FileOAuthAdapter example with credentials storage - Configuration summary with updated OAuthConfig interface
Adds missing exports to packages/core/src/index.ts: - registerOAuthClient function - ClientCredentials type - ClientMetadata type These were exported from client/index.ts but not re-exported from the main package index, causing them to be unavailable when importing from 'mcp-lite'.
50f3c36 to
992ae6c
Compare
CRITICAL: Fixed hardcoded protocol version in WWW-Authenticate fallback mechanism. Was using invalid '2024-11-05', now correctly uses SUPPORTED_MCP_PROTOCOL_VERSIONS.V2025_06_18. This incorrect protocol version could have caused MCP connection failures during OAuth discovery fallback when the server checks protocol version in initialize requests. Changes: - Import SUPPORTED_MCP_PROTOCOL_VERSIONS constant - Replace hardcoded '2024-11-05' with V2025_06_18 constant
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.
Why
Notes
Follow-ups