Skip to content

feat(typescript): add MCPToolProvider for MCP server integration#566

Open
cornelcroi wants to merge 1 commit into
mainfrom
feat/typescript-mcp-tool-provider
Open

feat(typescript): add MCPToolProvider for MCP server integration#566
cornelcroi wants to merge 1 commit into
mainfrom
feat/typescript-mcp-tool-provider

Conversation

@cornelcroi

Copy link
Copy Markdown
Collaborator

Issue Link (REQUIRED)

Fixes #299

Summary

Changes

Adds MCPToolProvider — a subclass of AgentTools that connects to one or more MCP servers (stdio or SSE transport) and exposes their tools transparently inside the existing toolConfig mechanism. No changes to any existing agent, classifier, or orchestrator.

  • New file: typescript/src/tools/mcpToolProvider.ts
    • MCPServerConfig interface covering stdio (command, args, env) and SSE (url, headers) transports
    • MCPToolProvider extends AgentTools with lazy connection, tool caching, and routing back to the correct server per tool call
    • toBedrockFormat(), toAnthropicFormat(), toOpenAIFormat() — pass MCP's JSON Schema through directly
    • isError results from MCP surfaced as error strings to the model
    • disconnect() for clean shutdown
  • typescript/package.json: @modelcontextprotocol/sdk >=1.0.0 in peerDependencies (optional, never forced)
  • typescript/src/index.ts: exports MCPToolProvider and MCPServerConfig
  • 20 unit tests — all 132 suite tests passing, lint clean

User experience

Before: no MCP support.

After:

import { MCPToolProvider, BedrockLLMAgent } from "agent-squad";

const agent = new BedrockLLMAgent({
    name: "my-agent",
    description: "An agent with MCP tools",
    toolConfig: {
        tool: new MCPToolProvider([
            { type: "stdio", command: "uvx", args: ["my-mcp-server"] },
            { type: "sse", url: "http://localhost:3000/sse" },
        ])
    }
});

Install: npm install agent-squad && npm install @modelcontextprotocol/sdk

Checklist

  • I have performed a self-review of this change
  • Changes have been tested
  • Changes are documented
  • I have linked this PR to an existing issue (required)

Acknowledgment

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Adds MCPToolProvider as a drop-in AgentTools subclass that connects to
one or more MCP servers (stdio or SSE) and exposes their tools transparently
inside the existing toolConfig mechanism — no changes to existing agents.

Closes #299

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 83b7e89c52

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +56 to +57
// Start with an empty tools array; populated lazily on first use
super([], callbacks);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Populate tools before formatting agent requests

When MCPToolProvider is passed to toolConfig.tool as shown, the constructor leaves tools empty and the only lazy connection points are to*Format() and toolHandler(). I checked the existing Bedrock and Anthropic flows: they build the initial request from tools.tools directly (BedrockLLMAgent.formatTools / AnthropicAgent.formatTools) and never call these new to*Format() methods, so the model receives an empty tool list and cannot produce a tool-use block that would trigger toolHandler(). This makes the advertised drop-in usage silently disable all MCP tools unless callers manually call ensureConnected() first.

Useful? React with 👍 / 👎.

Comment on lines +134 to +136
transport = new SSEClientTransport(new URL(serverConfig.url), {
headers: serverConfig.headers ?? {},
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Pass SSE headers via requestInit

When an SSE MCP server requires headers such as Authorization, these headers are ignored because the v1 SSEClientTransport options read custom request headers from requestInit.headers (and SSE setup from eventSourceInit), not from a top-level headers field. I checked the upstream v1 SDK source for SSEClientTransportOptions; passing { headers: ... } here means authenticated SSE servers still connect without the configured headers and fail with 401s.

Useful? React with 👍 / 👎.

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.

Feature request: MCP Servers and Tools

1 participant