Skip to content

feat(ai-proxy): add forest connectors#1505

Open
nbouliol wants to merge 18 commits intomainfrom
feat/ai-tools-integrations
Open

feat(ai-proxy): add forest connectors#1505
nbouliol wants to merge 18 commits intomainfrom
feat/ai-tools-integrations

Conversation

@nbouliol
Copy link
Copy Markdown
Member

@nbouliol nbouliol commented Mar 24, 2026

Definition of Done

General

  • Write an explicit title for the Pull Request, following Conventional Commits specification
  • Test manually the implemented changes
  • Validate the code quality (indentation, syntax, style, simplicity, readability)

Security

  • Consider the security impact of the changes made

Note

Add Zendesk and Brave Forest connector integrations to ai-proxy

  • Adds an IntegrationClient class that accepts ForestIntegrationConfig entries and loads tools from supported integrations (Zendesk, Brave) into the remote tools pipeline.
  • Implements six Zendesk DynamicStructuredTool operations: list tickets, get ticket, get ticket comments, create ticket, add comment, and update ticket — each wrapped as a ServerRemoteTool with sourceId: 'zendesk'.
  • Moves Brave search tool construction into the shared integrations layer via getIntegratedTools, keeping the existing brave_search tool behavior intact.
  • Extends Router.route to split incoming mcpConfigs into standard MCP server configs and Forest integration configs, constructing McpClient and IntegrationClient independently before merging their tools.
  • Extends McpConfigChecker.check to validate ForestIntegrationConfig entries — calling validateZendeskConfig for Zendesk and throwing on unsupported integration names.
  • Behavioral Change: McpConfiguration.configs now accepts either MCP server configs or ForestIntegrationConfig records; requests mixing both types are now split and handled separately.

Changes since #1505 opened

  • Introduced ToolProvider interface and createToolProviders factory [60b8a0c]
  • Refactored Router.route to accept and manage ToolProvider instances [60b8a0c]
  • Implemented ToolProvider interface in McpClient and IntegrationClient [60b8a0c]
  • Refactored McpConfigChecker.check to validate using ToolProvider abstraction [60b8a0c]
  • Updated createAiProvider factory to resolve and pass ToolProvider instances at routing time [60b8a0c]
  • Modified injectOauthTokens to operate on flat ToolSourceConfig records [60b8a0c]
  • Updated public API exports and added validation function with deprecated alias [60b8a0c]
  • Fixed error handling in validateZendeskConfig to handle non-JSON responses [60b8a0c]
  • Updated all test files to align with ToolProvider architecture [60b8a0c]
  • Renamed McpConfigChecker class to ToolSourceChecker and updated all imports, references, and test descriptions throughout the ai-proxy package [0f37a16]
  • Replaced locally defined AiRouterRouteArgs interface with type derived from @forestadmin/agent-toolkit AiRouter class [a891b59]
  • Removed deprecated export alias validMcpConfigurationOrThrow from the ai-proxy package [50f0037]
  • Updated test imports and descriptions to use validToolConfigurationOrThrow instead of removed alias [50f0037]
  • Refactored RemoteTools class to remove API key handling and integration configuration logic [ab6b929]
  • Refactored Router class to use a provider-based architecture for loading tools [ab6b929]
  • Implemented BraveToolProvider class as a concrete ToolProvider implementation [ab6b929]
  • Deleted integrations/tools.ts file and its associated test file [ab6b929]
  • Updated test files to align with new RemoteTools and Router constructor APIs and provider pattern [ab6b929]

Macroscope summarized 7ee4b1c.

@qltysh
Copy link
Copy Markdown

qltysh bot commented Mar 24, 2026

5 new issues

Tool Category Rule Count
qlty Duplication Found 23 lines of similar code in 2 locations (mass = 98) 2
qlty Structure Function with high complexity (count = 18): createUpdateTicketTool 2
qlty Structure Function with many returns (count = 4): route 1

@qltysh
Copy link
Copy Markdown

qltysh bot commented Mar 24, 2026

Qlty

Coverage Impact

⬆️ Merging this pull request will increase total coverage on main by 0.02%.

Modified Files with Diff Coverage (19)

RatingFile% DiffUncovered Line #s
Coverage rating: A Coverage rating: A
packages/ai-proxy/src/create-ai-provider.ts100.0%
Coverage rating: A Coverage rating: A
packages/ai-proxy/src/remote-tools.ts100.0%
Coverage rating: A Coverage rating: A
packages/ai-proxy/src/router.ts100.0%
Coverage rating: A Coverage rating: A
packages/ai-proxy/src/oauth-token-injector.ts100.0%
Coverage rating: A Coverage rating: A
packages/ai-proxy/src/mcp-client.ts100.0%
Coverage rating: A Coverage rating: A
packages/ai-proxy/src/index.ts100.0%
New file Coverage rating: A
packages/ai-proxy/src/integrations/zendesk/tools/get-tickets.ts100.0%
New file Coverage rating: A
packages/ai-proxy/src/integration-client.ts100.0%
New file Coverage rating: A
packages/ai-proxy/src/integrations/zendesk/tools/create-ticket.ts100.0%
New file Coverage rating: A
packages/ai-proxy/src/tool-provider-factory.ts100.0%
New file Coverage rating: A
packages/ai-proxy/src/integrations/zendesk/tools.ts100.0%
New file Coverage rating: C
packages/ai-proxy/src/integrations/brave/tools.ts75.0%12
New file Coverage rating: A
packages/ai-proxy/src/integrations/zendesk/tools/update-ticket.ts100.0%
New file Coverage rating: A
packages/ai-proxy/src/tool-source-checker.ts100.0%
New file Coverage rating: A
packages/ai-proxy/src/integrations/zendesk/utils.ts100.0%
New file Coverage rating: A
...-proxy/src/integrations/zendesk/tools/create-ticket-comment.ts100.0%
New file Coverage rating: A
packages/ai-proxy/src/integrations/zendesk/tools/get-ticket.ts100.0%
New file Coverage rating: A
...ai-proxy/src/integrations/zendesk/tools/get-ticket-comments.ts100.0%
New file Coverage rating: A
packages/ai-proxy/src/integrations/brave/brave-tool-provider.ts100.0%
Total99.4%
🤖 Increase coverage with AI coding...

In the `feat/ai-tools-integrations` branch, add test coverage for this new code:

- `packages/ai-proxy/src/integrations/brave/tools.ts` -- Line 12

🚦 See full report on Qlty Cloud »

🛟 Help
  • Diff Coverage: Coverage for added or modified lines of code (excludes deleted files). Learn more.

  • Total Coverage: Coverage for the whole repository, calculated as the sum of all File Coverage. Learn more.

  • File Coverage: Covered Lines divided by Covered Lines plus Missed Lines. (Excludes non-executable lines including blank lines and comments.)

    • Indirect Changes: Changes to File Coverage for files that were not modified in this PR. Learn more.

@nbouliol nbouliol force-pushed the feat/ai-tools-integrations branch from 4dd7990 to f4f1525 Compare March 25, 2026 16:31
@nbouliol nbouliol force-pushed the feat/ai-tools-integrations branch from f4f1525 to f4aa7a3 Compare March 25, 2026 16:49

export default class McpConfigChecker {
static check(mcpConfig: McpConfiguration) {
static isForestIntegrationConfig(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

could be private

alban bertolini and others added 5 commits March 27, 2026 11:38
Decouple Router from McpClient/IntegrationClient by introducing a
ToolProvider interface. Router now receives ToolProvider[] instead of
raw configs, and a factory handles the MCP vs integration split.

- Add ToolProvider interface (loadTools, checkConnection, dispose)
- Add createToolProviders factory to split configs
- McpClient/IntegrationClient implement ToolProvider
- Router accepts toolProviders[] instead of mcpConfigs
- McpConfigChecker uses factory instead of manual type guard
- Fix McpClient.loadTools() tool accumulation bug
- Fix validateZendeskConfig response.json() before response.ok check
- Clean McpConfiguration type (remove ForestIntegrationConfig union)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The class no longer has any MCP-specific logic — it delegates to the
ToolProvider factory. The new name reflects its actual responsibility.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use Parameters<AiRouter['route']>[0] from agent-toolkit instead of
maintaining a local copy that can diverge silently.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Internal lib, no need for backward compat shim.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ider

RemoteTools was both an aggregator and a Brave tool factory. Now Brave
is a ToolProvider like McpClient and IntegrationClient. RemoteTools
becomes a pure container.

- Add BraveToolProvider implementing ToolProvider
- Router creates BraveToolProvider from localToolsApiKeys
- Simplify RemoteTools constructor (no more apiKeys)
- Remove getIntegratedTools dispatcher (no longer needed)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants