Skip to content

feat: nearai mcp#1240

Open
hanakannzashi wants to merge 14 commits intostagingfrom
feat/nearai-mcp
Open

feat: nearai mcp#1240
hanakannzashi wants to merge 14 commits intostagingfrom
feat/nearai-mcp

Conversation

@hanakannzashi
Copy link

@hanakannzashi hanakannzashi commented Mar 16, 2026

Summary

  • Add a derived NEAR AI companion MCP integration so IronClaw can automatically discover and connect to ${nearai.base_url}/mcp when the active backend is nearai.
  • Reuse existing NEAR AI auth for MCP requests by sharing the same bearer-token resolution path used by the NearAI chat provider, avoiding separate MCP auth setup.
  • Normalize web_search MCP arguments before sending them upstream so invalid empty-string and malformed locale/freshness values do not break provider-backed search calls.
  • Wire the companion MCP server through app startup, extension loading, and MCP CLI flows, while keeping it derived-only rather than persisting it as a normal user MCP config.
  • Harden the integration by fixing constructor call sites, removing a runtime expect(...) panic in MCP client creation, preserving API-key-based auth reuse in the extension manager path, and preventing reserved companion-name collisions.

Change Type

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • CI/Infrastructure
  • Security
  • Dependencies

Linked Issue

Closes #548

Validation

  • cargo fmt
  • cargo clippy --all --benches --tests --examples --all-features
  • Relevant tests pass: cargo check -q passed; no dedicated automated test subset was run separately
  • Manual testing: validated local MCP integration against local cloud-api and chat-api MCP endpoints; confirmed IronClaw auto-derived _nearai_companion_mcp, ironclaw mcp test _nearai_companion_mcp succeeded without DB-backed config for the runtime-auth path, and the agent successfully executed provider-backed web search end-to-end

Security Impact

This change affects MCP auth and network calls. IronClaw now reuses the active NEAR AI provider auth for a derived companion MCP endpoint under the same base URL. The runtime auth bridge is scoped to the built-in NearAi auth source rather than arbitrary MCP servers, and the reserved companion server name cannot be user-defined or persisted accidentally.

Database Impact

None.

Blast Radius

Touches LLM auth resolution, MCP client creation, MCP config derivation, extension manager MCP loading, MCP CLI testing and persistence behavior, and provider-backed tool execution. Regressions could affect NearAI-backed MCP discovery, MCP auth header injection, extension reload/activation flows, CLI MCP management behavior, or provider-backed web search execution.

Rollback Plan

Revert the companion MCP integration commits to restore the previous behavior:

  • remove derived NEAR AI companion MCP server support
  • remove runtime NEAR AI auth bridging for MCP clients
  • remove web_search MCP argument normalization
  • restore previous MCP CLI handling without derived companion injection
  • fall back to existing MCP configuration behavior and existing Brave-based web search only

Review track: C

@github-actions github-actions bot added scope: channel/cli TUI / CLI channel scope: channel/web Web gateway channel scope: tool/builtin Built-in tools scope: tool/mcp MCP client scope: llm LLM integration scope: extensions Extension management size: L 200-499 changed lines risk: medium Business logic, config, or moderate-risk modules contributor: new First-time contributor labels Mar 16, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances IronClaw's integration with NEAR AI by introducing a companion Multi-Channel Protocol (MCP) server. This allows for seamless discovery and connection to NEAR AI's MCP endpoints, leveraging existing authentication for efficiency and security. Additionally, it refines the handling of web_search arguments to improve reliability and ensures the new MCP server is robustly integrated across all application lifecycle stages, from startup to extension management and CLI testing.

Highlights

  • NEAR AI Companion MCP Integration: Added a mechanism for IronClaw to automatically discover and connect to a companion MCP server derived from the active NEAR AI backend configuration.
  • Auth Reuse for MCP Requests: Implemented the reuse of existing NEAR AI authentication (session tokens or API keys) for requests made to the companion MCP server, avoiding redundant authentication setups.
  • Web Search Argument Normalization: Introduced logic to normalize web_search MCP arguments, cleaning up invalid empty strings and malformed locale/freshness values before sending them upstream.
  • Comprehensive Wiring: Ensured the companion MCP server is correctly wired through app startup, extension loading, and MCP CLI flows for consistent behavior.
  • Staging Integration Hardening: Fixed constructor call sites, prevented runtime panics in MCP client creation, and preserved API-key-based auth reuse in the extension manager path to harden the staging integration.
Changelog
  • .gitignore
    • Removed Python-related cache entries and added a .idea entry for JetBrains IDEs.
  • channels-src/whatsapp/Cargo.lock
    • Updated the version of the whatsapp-channel package to 0.2.0.
  • src/app.rs
    • Modified the application builder to derive and upsert a NEAR AI companion MCP server, and passed NEAR AI session and API key information to MCP client creation and the extension manager.
  • src/channels/web/server.rs
    • Updated test cases for ExtensionManager::new to accommodate new parameters for NEAR AI session, API key, and companion MCP server.
  • src/cli/mcp.rs
    • Enhanced the MCP CLI test_server command to correctly handle runtime authentication sources for MCP clients, specifically for NEAR AI, by passing session and API key details.
  • src/extensions/manager.rs
    • Extended the ExtensionManager to store and utilize NEAR AI session and API key information, and to incorporate the derived companion MCP server into its loaded server list.
  • src/llm/mod.rs
    • Introduced and re-exported the nearai_auth module, providing a centralized function for resolving NEAR AI bearer tokens.
  • src/llm/nearai_auth.rs
    • Added a new module containing resolve_nearai_bearer_token, a function that resolves NEAR AI authentication tokens based on a priority order of API key, existing session, interactive authentication, and environment variables.
  • src/llm/nearai_chat.rs
    • Refactored the resolve_bearer_token method to delegate its logic to the newly introduced resolve_nearai_bearer_token function.
  • src/tools/builtin/extension_tools.rs
    • Adjusted test cases for ExtensionManager::new to include new parameters for NEAR AI session, API key, and companion MCP server.
  • src/tools/mcp/client.rs
    • Augmented the McpClient with fields and methods to manage NEAR AI session and API key for runtime authentication, implemented a get_runtime_auth_token method, and added argument normalization for web_search tools.
  • src/tools/mcp/config.rs
    • Introduced McpAuthSource enum and an auth_source field to McpServerConfig, enabling runtime authentication. Added derive_nearai_companion_mcp_server to automatically configure a companion MCP server from NEAR AI settings.
  • src/tools/mcp/factory.rs
    • Updated create_client_from_config to accept NEAR AI session and API key, and to handle MCP servers that use runtime authentication sources, including a new error type for missing context.
  • tests/module_init_integration.rs
    • Modified test cases for ExtensionManager::new to pass None for the newly added NEAR AI session, API key, and companion MCP server parameters.
Activity
  • No human activity (comments, reviews, or progress updates) has been recorded for this pull request.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new feature for NEAR AI companion MCP integration, allowing IronClaw to automatically derive and connect to ${nearai.base_url}/mcp and reuse existing NEAR AI authentication. The changes involve updating McpClient, McpServerConfig, and ExtensionManager to handle the NEAR AI session manager and API key for authentication. A new module nearai_auth.rs centralizes the bearer token resolution logic, which is a good refactoring for maintainability. Additionally, web_search MCP arguments are now normalized to prevent invalid inputs from breaking upstream calls, enhancing robustness. The implementation appears solid, with appropriate updates to constructors, method signatures, and test cases across the affected modules.

@github-actions github-actions bot added size: XL 500+ changed lines and removed size: L 200-499 changed lines labels Mar 16, 2026
@hanakannzashi hanakannzashi removed the WIP label Mar 17, 2026
@hanakannzashi
Copy link
Author

@claude review

Copy link
Collaborator

@zmanian zmanian left a comment

Choose a reason for hiding this comment

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

Review: NEAR AI companion MCP integration

Good feature -- auto-deriving MCP config from the existing NEAR AI LLM backend eliminates manual setup. No new dependencies, secrets handled with SecretString, no .unwrap() in production paths. CI green.

Concerning: Web search argument normalization too permissive

The final commit narrows normalization to only strip empty strings via map.retain(). This means invalid enum values for freshness (only "pd", "pw", "pm", "py" are valid) pass through unchecked. An LLM hallucinating "freshness": "invalid" would hit the upstream API raw.

Suggestion: keep the current retain-empty approach but add explicit validation for freshness values since it's a closed enum.

Concerning: Incomplete reserved server protection

CLI prevents removing and toggling the companion server, and auth_server() returns early for runtime-auth servers. But there's no protection against manual JSON config edits that could override the derived server config. Consider validating at load time that _nearai_companion_mcp entries match the derived config.

Minor: Test feature gate

test_derive_nearai_companion_mcp_server_strips_trailing_v1 is gated with #[cfg(feature = "libsql")] but the function under test has no DB dependencies. Should compile unconditionally or use #[cfg(any(feature = "libsql", feature = "postgres"))].

Minor: NEARAI_API_KEY env var not wrapped in SecretString

In nearai_auth.rs, the NEARAI_API_KEY env fallback returns a raw String rather than being wrapped in SecretString like the keychain-sourced credential. Low risk since it's only passed to the LLM provider, but inconsistent with the rest of the secret handling.

What's good

  • Clean auto-derivation: derive_nearai_companion_mcp_server() constructs MCP config from LLM config without duplicating secrets
  • Underscore-prefixed _nearai_companion_mcp name signals "system-managed"
  • is_derived flag prevents persistence of ephemeral config
  • Factory error handling properly uses McpFactoryError::MissingRuntimeAuthContext
  • Good test coverage for derivation, CLI protection, and header injection

@henrypark133 henrypark133 requested a review from Copilot March 18, 2026 21:29
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a derived “NEAR AI companion” MCP server integration so IronClaw can auto-discover a NearAI-backed MCP endpoint and reuse NearAI auth for MCP requests, wiring it through startup, extensions, and CLI flows.

Changes:

  • Introduces McpAuthSource::NearAi + derived companion server config (_nearai_companion_mcp) and plumbs runtime NearAI auth context into MCP client creation.
  • Centralizes NearAI bearer-token resolution into resolve_nearai_bearer_token and reuses it for both chat and MCP.
  • Updates extension/web types to surface “derived” extensions and adjusts CLI MCP commands to include derived servers while preventing user management of the reserved companion.

Reviewed changes

Copilot reviewed 15 out of 17 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/module_init_integration.rs Updates ExtensionManager::new call site for new constructor args.
src/tools/mcp/factory.rs Adds runtime-auth context parameters and creates MCP clients with NearAI auth reuse.
src/tools/mcp/config.rs Adds auth_source, reserved companion name, derivation helper, and insert-if-absent behavior.
src/tools/mcp/client.rs Adds NearAI runtime auth header injection and web_search argument normalization.
src/tools/builtin/extension_tools.rs Updates ExtensionManager::new test stub for new args.
src/llm/nearai_chat.rs Switches bearer-token resolution to shared helper.
src/llm/nearai_auth.rs New module factoring NearAI bearer-token resolution logic.
src/llm/mod.rs Exposes nearai_auth module and re-exports resolver.
src/extensions/mod.rs Adds derived flag to installed extension representation.
src/extensions/manager.rs Loads derived companion MCP server, adds runtime-auth checks, and tags derived extensions.
src/cli/mcp.rs Includes derived servers in list/auth/test, prevents reserved-name management, filters derived servers from persistence.
src/channels/web/types.rs Adds derived to web API extension payload type.
src/channels/web/server.rs Wires derived through extensions list handler/tests and updates constructor args.
src/channels/web/handlers/extensions.rs Wires derived through extensions list handler.
src/app.rs Derives companion MCP server at startup and passes NearAI auth context into MCP activation flows.
channels-src/whatsapp/Cargo.lock Bumps whatsapp-channel lockfile version entry.
.gitignore Adds Python artifact patterns and JetBrains .idea ignore.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}

fn resolve_llm_from_env() -> Result<LlmConfig, crate::error::ConfigError> {
LlmConfig::resolve(&Settings::default())
///
/// This is used for companion MCP servers that should reuse an existing
/// provider identity instead of running their own MCP OAuth flow.
#[serde(default, skip_serializing_if = "Option::is_none")]
// model frequently emits as empty strings. Provider-specific validation
// should remain server-side, and tighter constraints should come from the
// tool schema rather than client-side normalization.
map.retain(|_, value| !value.as_str().is_some_and(|s| s.trim().is_empty()));
Comment on lines +33 to +36
if let Ok(key) = std::env::var("NEARAI_API_KEY")
&& !key.is_empty()
{
return Ok(key);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: new First-time contributor risk: medium Business logic, config, or moderate-risk modules scope: channel/cli TUI / CLI channel scope: channel/web Web gateway channel scope: extensions Extension management scope: llm LLM integration scope: tool/builtin Built-in tools scope: tool/mcp MCP client size: XL 500+ changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Search to Chat API

3 participants