Skip to content
This repository was archived by the owner on Apr 12, 2026. It is now read-only.

Fix: pass httpHeaders to streamable HTTP transport#167

Open
jimmynail wants to merge 8 commits into
tuannvm:mainfrom
belliwelli:fix/http-transport-headers
Open

Fix: pass httpHeaders to streamable HTTP transport#167
jimmynail wants to merge 8 commits into
tuannvm:mainfrom
belliwelli:fix/http-transport-headers

Conversation

@jimmynail
Copy link
Copy Markdown

@jimmynail jimmynail commented Feb 13, 2026

Summary

  • HTTP (streamable) transport now passes httpHeaders from config to the MCP client via transport.WithHTTPHeaders()
  • Previously only SSE transport forwarded custom headers; HTTP transport ignored them

Problem

MCP servers requiring Bearer token auth (e.g., Omni) fail with Authentication required when using the http transport because headers aren't forwarded.

Fixes #166

Test plan

  • Verify HTTP transport connects to an MCP server with Bearer auth
  • Verify SSE transport still works unchanged

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Bot now tracks active threads so follow-up messages in threads are recognized and handled.
  • Bug Fixes

    • Custom HTTP headers are now included in outgoing streamable HTTP requests.
    • Slack callback handling ignores intermediate tool-output, strips leading "AI:" from final replies, and only sends non-empty final messages.
    • Tool failures are surfaced as structured tool responses (not runtime errors), improving agent resilience.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 13, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds passing of configured HTTP headers into the streamable MCP HTTP transport; adds Slack client thread-tracking for follow-ups and hardens final assistant-text extraction/filtering before sending.

Changes

Cohort / File(s) Summary
MCP HTTP transport
internal/mcp/client.go
Import transport, convert resolvedHeaders into map[string]string, and pass them to the streamable HTTP client so http transport includes configured HTTP headers.
Slack client & callback handling
internal/slack/client.go, internal/slack/agentCallbackHandler.go
Add activeThreads map[string]bool and initialize it; track app-mention threads and treat messages in tracked threads as follow-ups. Refactor HandleChainEnd to safely read outputs["text"], skip intermediate tool messages, strip leading AI: prefix, and only send non-empty final text.
MCP Tool error handling
internal/mcp/mcpTool.go
On tool call failure, embed the error into the tool result string (prefixed with [Tool Error] ...) and return nil error so the agent loop receives the error as text rather than a Go error.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • tuannvm

Poem

"I hopped through headers, light and fleet,
Carried tokens where servers meet.
I keep the threads both warm and bright,
Trim the fluff, deliver right.
🥕 — a rabbit, coding through the night."

🚥 Pre-merge checks | ✅ 4 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR partially addresses #166's core requirement but introduces unrelated changes to Slack handler logic (agentCallbackHandler.go, client.go) and tool error handling (mcpTool.go) beyond the HTTP headers fix. The PR should focus on the HTTP headers fix for #166. Separate the Slack and tool error handling changes into distinct PRs to maintain clear issue-to-code traceability.
Out of Scope Changes check ⚠️ Warning Multiple unrelated changes are included: Slack thread tracking (activeThreads map), Slack message filtering logic, and tool error string embedding—none of which relate to the HTTP headers transport fix in #166. Extract Slack callback/client and mcpTool.go changes into separate feature branches and PRs to keep this PR focused on resolving the #166 issue.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title directly addresses the main change: passing httpHeaders to HTTP transport, which is the primary fix in internal/mcp/client.go.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@jimmynail jimmynail force-pushed the fix/http-transport-headers branch from 28dd8bd to 173c0aa Compare February 13, 2026 14:35
The HTTP transport was ignoring httpHeaders from config, causing auth
failures for MCP servers that require Bearer token auth (e.g., Omni).

Uses aliased import to avoid shadowing the 'transport' parameter name.

Fixes tuannvm#166

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Tyson Woeste <tyson@belliwelli.com>
@jimmynail jimmynail force-pushed the fix/http-transport-headers branch from 173c0aa to 3beae6c Compare February 13, 2026 17:17
Tyson Woeste and others added 2 commits February 13, 2026 10:21
The agentCallbackHandler.HandleChainEnd was sending every intermediate
agent step to the user, including internal "Thought:", "Action:", and
"Action Input:" reasoning text. This changes the handler to:

1. Suppress intermediate tool-calling steps (containing Action/Action Input)
2. Strip the "Thought: Do I need to use a tool? No / AI:" prefix from
   the final answer
3. Only send the clean final response to the user

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Tyson Woeste <tyson@belliwelli.com>
Track active threads when the bot is @mentioned, then respond to
follow-up messages in those threads without requiring another @mention.
This gives natural flowing conversation in threads.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@internal/slack/client.go`:
- Line 40: activeThreads currently uses map[string]bool and is never evicted,
causing unbounded growth; change it to store timestamps (e.g.,
map[string]time.Time or map[string]int64) instead of bool, update the code paths
that insert keys (the AppMentionEvent handling where entries are added) to write
time.Now(), and add a pruning strategy — either a simple TTL-based prune helper
that removes entries older than N (called periodically via a background
goroutine or lazily on writes/reads), or replace with a bounded LRU structure;
ensure all access to activeThreads is protected by the existing mutex (or add
one) when reading/writing to avoid races.

Comment thread internal/slack/client.go
historyLimit int
discoveredTools map[string]mcp.ToolInfo
tracingHandler observability.TracingHandler
activeThreads map[string]bool // channel:threadTS keys where bot has been mentioned
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Unbounded growth of activeThreads map — entries are added but never evicted.

Every AppMentionEvent inserts a key into activeThreads, but there is no expiration, size cap, or cleanup path. For a long-running bot in an active workspace this map will grow indefinitely, leaking memory.

Consider one of:

  • A TTL-based eviction (e.g., remove entries older than N hours using a timestamp value instead of bool).
  • A bounded LRU / ring buffer.
  • Periodic pruning in a background goroutine.
Example: store timestamps and add a simple pruning helper
-	activeThreads   map[string]bool // channel:threadTS keys where bot has been mentioned
+	activeThreads   map[string]time.Time // channel:threadTS → last-activity time
-		c.activeThreads[threadKey] = true
+		c.activeThreads[threadKey] = time.Now()
-			isActiveThread = c.activeThreads[threadKey]
+			if ts, ok := c.activeThreads[threadKey]; ok && time.Since(ts) < 24*time.Hour {
+				isActiveThread = true
+			}

And periodically (or lazily) prune stale entries.

Also applies to: 269-273

🤖 Prompt for AI Agents
In `@internal/slack/client.go` at line 40, activeThreads currently uses
map[string]bool and is never evicted, causing unbounded growth; change it to
store timestamps (e.g., map[string]time.Time or map[string]int64) instead of
bool, update the code paths that insert keys (the AppMentionEvent handling where
entries are added) to write time.Now(), and add a pruning strategy — either a
simple TTL-based prune helper that removes entries older than N (called
periodically via a background goroutine or lazily on writes/reads), or replace
with a bounded LRU structure; ensure all access to activeThreads is protected by
the existing mutex (or add one) when reading/writing to avoid races.

Tyson Woeste and others added 5 commits February 13, 2026 14:09
When an MCP tool call fails (e.g., 504 timeout, auth error), return the
error message as a tool result string instead of a Go error. This lets
the LLM agent see what happened and retry or use a different approach,
rather than crashing the entire agent loop and returning an error to the
user.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of a static "Querying Cerebro..." indicator, randomly pick from
a pool of short phrases like "On it...", "Digging in...", "Crunching..."
etc. The cleanup logic matches against any known thinking message.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two changes that prevent the agent loop from crashing when Claude
produces non-conformant ReAct output:

1. Enable ParserErrorHandler on the executor so parse failures get
   fed back to the LLM as observations instead of killing the loop.
   The LLM can self-correct on the next iteration.

2. Make JSON unmarshal errors in mcpTool.go non-fatal, same pattern
   as the existing MCP call error resilience. Returns the error as
   a tool result string so the LLM can retry with valid JSON.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Handle socketmode.EventTypeSlashCommand in the event loop.
For /cerebro-status, proxy to the local status-server sidecar
on localhost:8081 and return Block Kit JSON via Ack.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HTTP (streamable) transport ignores httpHeaders config

1 participant