---
phase: 26-add-oauth-support-to-load-testing
plan: 02
type: execute
wave: 2
depends_on: ["26-01"]
files_modified:
  - crates/mcp-tester/Cargo.toml
  - crates/mcp-tester/src/lib.rs
  - crates/mcp-tester/src/main.rs
  - crates/mcp-tester/src/oauth.rs
autonomous: true
requirements:
  - OAUTH-03

must_haves:
  truths:
    - "mcp-tester imports OAuthHelper, OAuthConfig, default_cache_path from pmcp::client::oauth instead of its own oauth module"
    - "crates/mcp-tester/src/oauth.rs is deleted (or emptied to a thin re-export)"
    - "All existing mcp-tester functionality works identically (no behavioral change)"
    - "cargo test -p mcp-tester compiles and passes"
    - "cargo build -p mcp-tester succeeds"
  artifacts:
    - path: "crates/mcp-tester/Cargo.toml"
      provides: "pmcp dependency with oauth feature enabled"
      contains: "oauth"
    - path: "crates/mcp-tester/src/main.rs"
      provides: "Updated imports from pmcp::client::oauth"
      contains: "pmcp::client::oauth"
    - path: "crates/mcp-tester/src/lib.rs"
      provides: "Re-exports from pmcp::client::oauth instead of local oauth module"
      contains: "pmcp::client::oauth"
  key_links:
    - from: "crates/mcp-tester/src/main.rs"
      to: "src/client/oauth.rs"
      via: "imports OAuthHelper, OAuthConfig, default_cache_path from pmcp::client::oauth"
      pattern: "pmcp::client::oauth"
    - from: "crates/mcp-tester/src/lib.rs"
      to: "src/client/oauth.rs"
      via: "re-exports pmcp::client::oauth types for backward compat"
      pattern: "pub use pmcp::client::oauth"
---

<objective>
Update mcp-tester to use the SDK's OAuthHelper instead of its own copy. Delete the local oauth.rs and import from pmcp::client::oauth.

Purpose: After plan 01 moved OAuthHelper to the core SDK, mcp-tester should consume it from there instead of maintaining its own copy. This eliminates code duplication and ensures both mcp-tester and cargo-pmcp loadtest use the same OAuth implementation.

Output: mcp-tester builds against pmcp's oauth module. Local oauth.rs deleted. All existing tests pass.
</objective>

<execution_context>
@./.claude/get-shit-done/workflows/execute-plan.md
@./.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/26-add-oauth-support-to-load-testing/26-CONTEXT.md
@.planning/phases/26-add-oauth-support-to-load-testing/26-01-SUMMARY.md

<interfaces>
<!-- After plan 01, these types are available from pmcp::client::oauth -->
From src/client/oauth.rs (created by plan 01):
```rust
pub struct OAuthConfig {
    pub issuer: Option<String>,
    pub mcp_server_url: Option<String>,
    pub client_id: String,
    pub scopes: Vec<String>,
    pub cache_file: Option<PathBuf>,
    pub redirect_port: u16,
}

pub struct OAuthHelper { /* config + client */ }
impl OAuthHelper {
    pub fn new(config: OAuthConfig) -> pmcp::Result<Self>;
    pub async fn get_access_token(&self) -> pmcp::Result<String>;
    pub async fn create_middleware_chain(&self) -> pmcp::Result<Arc<HttpMiddlewareChain>>;
}

pub fn default_cache_path() -> PathBuf;
pub async fn create_oauth_middleware(config: OAuthConfig) -> pmcp::Result<Arc<HttpMiddlewareChain>>;
```

From crates/mcp-tester/src/main.rs (current -- to be updated):
```rust
use oauth::{OAuthConfig, OAuthHelper};
// ...
async fn create_oauth_middleware(...) -> Result<Option<Arc<HttpMiddlewareChain>>> {
    // Constructs OAuthConfig from CLI flags, calls OAuthHelper::new + create_middleware_chain
}
```

From crates/mcp-tester/src/lib.rs (current -- to be updated):
```rust
pub mod oauth;
pub use oauth::{OAuthConfig, OAuthHelper};
```
</interfaces>
</context>

<tasks>

<task type="auto">
  <name>Task 1: Enable oauth feature in mcp-tester's pmcp dependency and update lib.rs</name>
  <files>crates/mcp-tester/Cargo.toml, crates/mcp-tester/src/lib.rs</files>
  <action>
**Cargo.toml:**
Update the pmcp dependency to enable the `oauth` feature:
```toml
pmcp = { version = "1.11.0", path = "../../", features = ["streamable-http", "oauth"] }
```

Remove deps that are now provided by pmcp's oauth feature (only if they were ONLY used by the local oauth.rs):
- `webbrowser` -- only used by oauth.rs -> REMOVE
- `dirs` -- only used by oauth.rs -> REMOVE
- Keep `sha2`, `base64`, `rand`, `url` -- these may be used elsewhere in mcp-tester (check before removing)
- Keep `colored` -- still used by main.rs and other modules for terminal output

Actually, check each dep:
- `sha2 = "0.10"` -- only used in oauth.rs -> REMOVE
- `base64 = "0.22"` -- only used in oauth.rs -> REMOVE
- `webbrowser = "1"` -- only used in oauth.rs -> REMOVE
- `dirs = "6"` -- only used in oauth.rs -> REMOVE
- `rand = "0.10"` -- check if used elsewhere in mcp-tester. If only in oauth.rs -> REMOVE
- `url = "2"` -- may be used in tester.rs or other modules -> CHECK before removing

To be safe: grep each crate name across mcp-tester src files (excluding oauth.rs) before removing.

**lib.rs:**
Replace the local `pub mod oauth;` with a re-export from pmcp:

```rust
// OAuth support -- re-exported from core SDK
pub use pmcp::client::oauth;
pub use pmcp::client::oauth::{OAuthConfig, OAuthHelper};
```

This preserves backward compatibility: any code doing `use mcp_tester::{OAuthConfig, OAuthHelper}` or `use mcp_tester::oauth::default_cache_path` still works, but the types now come from pmcp.
  </action>
  <verify>
    <automated>cd /Users/guy/Development/mcp/sdk/rust-mcp-sdk && cargo check -p mcp-tester 2>&1 | tail -5</automated>
  </verify>
  <done>mcp-tester's Cargo.toml has `oauth` feature enabled on pmcp dep. Unused deps removed. lib.rs re-exports from pmcp::client::oauth. cargo check succeeds.</done>
</task>

<task type="auto">
  <name>Task 2: Delete local oauth.rs and update main.rs imports</name>
  <files>crates/mcp-tester/src/oauth.rs, crates/mcp-tester/src/main.rs</files>
  <action>
**Delete crates/mcp-tester/src/oauth.rs:**
Remove the file entirely. The types are now provided by pmcp::client::oauth.

**Update main.rs:**
1. Replace `use oauth::{OAuthConfig, OAuthHelper};` with:
   ```rust
   use pmcp::client::oauth::{OAuthConfig, OAuthHelper, default_cache_path};
   ```

2. Remove `mod oauth;` declaration (it was declared in main.rs before).

3. In `create_oauth_middleware` function, update the `default_cache_path()` call:
   - Was: `oauth::default_cache_path()` (local module)
   - Now: `default_cache_path()` (imported above)

4. The `create_oauth_middleware` function in main.rs should STAY -- it's a thin CLI-specific wrapper that:
   - Takes CLI flag values as parameters
   - Returns `Result<Option<Arc<HttpMiddlewareChain>>>` (Option because it returns None when no client_id)
   - Constructs OAuthConfig from CLI flags
   - Calls OAuthHelper::new + create_middleware_chain
   - Handles the "warning if issuer without client_id" case

   But update its error handling: OAuthHelper::new now returns `pmcp::error::Result`, not `anyhow::Result`. The `?` operator will auto-convert since main.rs uses `anyhow::Result` and pmcp::error::Error implements `std::error::Error`.

5. The `create_oauth_from_config` helper function stays as-is (just calls create_oauth_middleware).

6. Note about `colored` output in main.rs: The main.rs still uses `colored` for its own terminal output (print_header, etc.). This is fine -- colored is an application concern. Only the SDK (pmcp crate) avoids colored.

**Important:** The `OAuthHelper::new` now returns `pmcp::error::Result` instead of `anyhow::Result`. In main.rs which uses `anyhow::Result`, the `?` operator should work because pmcp::error::Error likely implements `std::error::Error`. If not, wrap with `.map_err(|e| anyhow::anyhow!("{e}"))?`.
  </action>
  <verify>
    <automated>cd /Users/guy/Development/mcp/sdk/rust-mcp-sdk && cargo build -p mcp-tester 2>&1 | tail -5 && cargo test -p mcp-tester --lib -- --test-threads=1 2>&1 | tail -5</automated>
  </verify>
  <done>crates/mcp-tester/src/oauth.rs is deleted. main.rs imports from pmcp::client::oauth. cargo build -p mcp-tester succeeds. All existing mcp-tester tests pass. mcp-tester CLI behavior is identical.</done>
</task>

</tasks>

<verification>
```bash
cd /Users/guy/Development/mcp/sdk/rust-mcp-sdk

# Build
cargo build -p mcp-tester

# Tests
cargo test -p mcp-tester -- --test-threads=1

# Verify oauth.rs is gone
test ! -f crates/mcp-tester/src/oauth.rs && echo "oauth.rs deleted" || echo "FAIL: oauth.rs still exists"

# Verify re-export works
cargo doc -p mcp-tester --no-deps 2>&1 | tail -5

# Clippy
cargo clippy -p mcp-tester -- -D warnings
```
</verification>

<success_criteria>
1. `crates/mcp-tester/src/oauth.rs` does not exist
2. `cargo build -p mcp-tester` succeeds
3. `cargo test -p mcp-tester` passes (all existing tests)
4. mcp-tester CLI `--oauth-client-id` flag still works (same behavior)
5. `mcp_tester::OAuthConfig` and `mcp_tester::OAuthHelper` re-exports still resolve
</success_criteria>

<output>
After completion, create `.planning/phases/26-add-oauth-support-to-load-testing/26-02-SUMMARY.md`
</output>
