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

fix: skip Slack context parameters in tool call execution#124

Open
domnikl wants to merge 1 commit into
tuannvm:mainfrom
yazio:not-send-slack-context-to-tool-call
Open

fix: skip Slack context parameters in tool call execution#124
domnikl wants to merge 1 commit into
tuannvm:mainfrom
yazio:not-send-slack-context-to-tool-call

Conversation

@domnikl
Copy link
Copy Markdown

@domnikl domnikl commented Sep 9, 2025

I noticed some MCP servers don't quite like having the channel_id and thread_ts from Slack context when executing tool calls, namely the Notion MCP was having problems with that and thus I removed that from the tool call.

Summary by CodeRabbit

  • Bug Fixes
    • Prevents Slack metadata (e.g., channel and thread identifiers) from being passed to tools as input, reducing unintended arguments and improving reliability of tool executions from Slack-originated actions.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Sep 9, 2025

Walkthrough

Introduces a guard in LLMMCPBridge.executeToolCall to ignore Slack-specific context keys ("channel_id", "thread_ts") when merging extraArgs into toolCall.Args, with a debug log on skipped keys. No changes to function signatures or broader flow.

Changes

Cohort / File(s) Summary
LLM MCP Bridge handler
internal/handlers/llm_mcp_bridge.go
Added conditional filter to exclude "channel_id" and "thread_ts" from extraArgs when constructing toolCall.Args; added debug logging for skipped keys; no public API changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Caller
  participant LLMMCPBridge as LLMMCPBridge.executeToolCall
  participant Tool as ToolExecutor
  Caller->>LLMMCPBridge: executeToolCall(toolCall, extraArgs, ctx)
  LLMMCPBridge->>LLMMCPBridge: Merge toolCall.Args with extraArgs
  note over LLMMCPBridge: Skip keys: "channel_id", "thread_ts"<br/>Log debug when skipping
  LLMMCPBridge->>Tool: Invoke with merged args (filtered)
  Tool-->>LLMMCPBridge: Result/Response
  LLMMCPBridge-->>Caller: Return result
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Pre-merge checks (3 passed)

✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The title clearly and concisely describes the primary change of skipping Slack context parameters during tool call execution, directly reflecting the main issue addressed by the pull request.
Description Check ✅ Passed The description clearly explains the context and rationale for removing Slack context parameters and directly relates to the code changes by illustrating the motivation behind the fix.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.

Poem

A whisk of keys, a hop so light,
I sift the args by moonlit byte—
Slack threads stay out, tools get the right,
Debugs twinkle in the night.
Thump-thump, ship it—clean and tight! 🐇✨

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • 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.

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

🧹 Nitpick comments (2)
internal/handlers/llm_mcp_bridge.go (2)

451-456: Avoid overriding LLM-provided args with transport extras

Prevent silent clobbering of fields if both the LLM and extraArgs provide the same key.

-		toolCall.Args[k] = v
+		if _, exists := toolCall.Args[k]; !exists {
+			toolCall.Args[k] = v
+		} else {
+			b.logger.DebugKV("Not overriding existing arg with extraArg", "key", k, "tool", toolCall.Tool)
+		}

457-471: Don’t log full args payloads; log only keys/count to reduce accidental PII leakage

Current logs emit the entire args map. Safer to log keys and count.

-	b.logger.DebugKV("Executing tool call",
-		"tool", toolCall.Tool,
-		"args", fmt.Sprintf("%v", toolCall.Args))
+	argKeys := make([]string, 0, len(toolCall.Args))
+	for k := range toolCall.Args {
+		argKeys = append(argKeys, k)
+	}
+	b.logger.DebugKV("Executing tool call",
+		"tool", toolCall.Tool,
+		"args_count", len(toolCall.Args),
+		"arg_keys", strings.Join(argKeys, ","))
@@
-	b.logger.InfoKV("Calling MCP tool",
-		"tool", toolCall.Tool,
-		"server", serverName,
-		"args", fmt.Sprintf("%v", toolCall.Args))
+	b.logger.InfoKV("Calling MCP tool",
+		"tool", toolCall.Tool,
+		"server", serverName,
+		"args_count", len(toolCall.Args),
+		"arg_keys", strings.Join(argKeys, ","))

Note: strings is already imported; no extra imports needed.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1790fe4 and 5ed56f8.

📒 Files selected for processing (1)
  • internal/handlers/llm_mcp_bridge.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
internal/handlers/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

Tool handlers and LLM-MCP bridge should be implemented in internal/handlers/

Files:

  • internal/handlers/llm_mcp_bridge.go
🧠 Learnings (1)
📚 Learning: 2025-07-20T02:54:03.119Z
Learnt from: CR
PR: tuannvm/slack-mcp-client#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-20T02:54:03.119Z
Learning: Applies to internal/handlers/**/*.go : Tool handlers and LLM-MCP bridge should be implemented in `internal/handlers/`

Applied to files:

  • internal/handlers/llm_mcp_bridge.go
🧬 Code graph analysis (1)
internal/handlers/llm_mcp_bridge.go (1)
internal/slack/client.go (1)
  • c (611-786)
🔇 Additional comments (1)
internal/handlers/llm_mcp_bridge.go (1)

1-3: Placement aligns with project guidelines

LLM–MCP bridge lives under internal/handlers as required. No action needed.

Comment on lines +445 to +449
// Skip Slack context parameters as they're for internal tracking, not tool parameters
if k == "channel_id" || k == "thread_ts" {
b.logger.DebugKV("Skipping Slack context parameter", "key", k, "tool", toolCall.Tool)
continue
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Good guard, but also scrub these keys from toolCall.Args to fully meet the PR objective

Right now we only skip adding Slack context from extraArgs. If the LLM (or upstream) already put channel_id or thread_ts into toolCall.Args, they’ll still be sent to MCP. Scrub them from toolCall.Args as well and centralize the denylist to avoid drift.

Apply:

 func (b *LLMMCPBridge) executeToolCall(ctx context.Context, toolCall *ToolCall, extraArgs map[string]interface{}) (string, error) {
-	for k, v := range extraArgs {
-		// Skip Slack context parameters as they're for internal tracking, not tool parameters
-		if k == "channel_id" || k == "thread_ts" {
-			b.logger.DebugKV("Skipping Slack context parameter", "key", k, "tool", toolCall.Tool)
-			continue
-		}
+	// Denylist of Slack context keys that must never be forwarded to MCP tools
+	disallowedKeys := map[string]struct{}{
+		"channel_id": {},
+		"thread_ts":  {},
+	}
+
+	// Also scrub these keys if they were present in the LLM-supplied args
+	if toolCall.Args != nil {
+		for k := range disallowedKeys {
+			if _, ok := toolCall.Args[k]; ok {
+				b.logger.DebugKV("Removing disallowed argument from tool args", "key", k, "tool", toolCall.Tool)
+				delete(toolCall.Args, k)
+			}
+		}
+	}
+
+	for k, v := range extraArgs {
+		// Skip Slack context parameters as they're for internal tracking, not tool parameters
+		if _, disallowed := disallowedKeys[k]; disallowed {
+			b.logger.DebugKV("Skipping Slack context parameter", "key", k, "tool", toolCall.Tool)
+			continue
+		}
 
 		// Add any extra arguments to the tool call args
 		if toolCall.Args == nil {
 			toolCall.Args = make(map[string]interface{})
 		}
 		toolCall.Args[k] = v
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Skip Slack context parameters as they're for internal tracking, not tool parameters
if k == "channel_id" || k == "thread_ts" {
b.logger.DebugKV("Skipping Slack context parameter", "key", k, "tool", toolCall.Tool)
continue
}
func (b *LLMMCPBridge) executeToolCall(ctx context.Context, toolCall *ToolCall, extraArgs map[string]interface{}) (string, error) {
// Denylist of Slack context keys that must never be forwarded to MCP tools
disallowedKeys := map[string]struct{}{
"channel_id": {},
"thread_ts": {},
}
// Also scrub these keys if they were present in the LLM-supplied args
if toolCall.Args != nil {
for k := range disallowedKeys {
if _, ok := toolCall.Args[k]; ok {
b.logger.DebugKV("Removing disallowed argument from tool args", "key", k, "tool", toolCall.Tool)
delete(toolCall.Args, k)
}
}
}
for k, v := range extraArgs {
// Skip Slack context parameters as they're for internal tracking, not tool parameters
if _, disallowed := disallowedKeys[k]; disallowed {
b.logger.DebugKV("Skipping Slack context parameter", "key", k, "tool", toolCall.Tool)
continue
}
// Add any extra arguments to the tool call args
if toolCall.Args == nil {
toolCall.Args = make(map[string]interface{})
}
toolCall.Args[k] = v
}
// ... rest of executeToolCall ...
}
🤖 Prompt for AI Agents
In internal/handlers/llm_mcp_bridge.go around lines 445 to 449, the current
guard skips adding Slack context keys from extraArgs but does not remove them if
they already exist in toolCall.Args; update the code to centralize a denylist
(e.g., a package-level slice or map containing "channel_id" and "thread_ts") and
before sending to MCP iterate that denylist to delete those keys from
toolCall.Args (and extraArgs if still needed), keeping the existing DebugKV log
when a key is found and removed; ensure the denylist is reused wherever similar
filtering is required to avoid drift.

@sfc-gh-jsummer
Copy link
Copy Markdown

I'm encountering this error as well due to the slack context arguments being injected into a narrowly scoped MCP tool schema.

@rangamani54
Copy link
Copy Markdown
Contributor

rangamani54 commented Sep 13, 2025

This has been added to have better context of threads for summarizing threads and accomplish further. As anyway we are adding thread conversation to context history, but sometimes when using slack mcp server requires slack channel id and thread ts. It would be better if we have a flag and disallowed/allowed parameters or disallowed/alllowed tools/mcp servers to have extra parameters. And handling this from config block

@rangamani54
Copy link
Copy Markdown
Contributor

This has been added to have better context of threads for summarizing threads and accomplish further. As anyway we are adding thread conversation to context history, but sometimes when using slack mcp server requires slack channel id and thread ts. It would be better if we have a flag and disallowed/allowed parameters or disallowed/alllowed tools/mcp servers to have extra parameters. And handling this from config block

@tuannvm what do you think of this

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.

3 participants