Skip to content

Commit f84faf0

Browse files
feat(anthropic): support for mcp toolset tool
1 parent 0649a20 commit f84faf0

File tree

7 files changed

+485
-0
lines changed

7 files changed

+485
-0
lines changed

libs/providers/langchain-anthropic/README.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,143 @@ console.log(response.tool_calls?.[0].args.command); // "ls -la *.py"
563563

564564
For more information, see [Anthropic's Bash Tool documentation](https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/bash-tool).
565565

566+
### MCP Toolset
567+
568+
The MCP toolset (`mcpToolset_20251120`) enables Claude to connect to remote MCP (Model Context Protocol) servers directly from the Messages API without implementing a separate MCP client. This allows Claude to use tools provided by MCP servers.
569+
570+
Key features:
571+
572+
- **Direct API integration** - Connect to MCP servers without implementing an MCP client
573+
- **Tool calling support** - Access MCP tools through the Messages API
574+
- **Flexible tool configuration** - Enable all tools, allowlist specific tools, or denylist unwanted tools
575+
- **Per-tool configuration** - Configure individual tools with custom settings
576+
- **OAuth authentication** - Support for OAuth Bearer tokens for authenticated servers
577+
- **Multiple servers** - Connect to multiple MCP servers in a single request
578+
579+
```typescript
580+
import { ChatAnthropic, tools } from "@langchain/anthropic";
581+
582+
const llm = new ChatAnthropic({
583+
model: "claude-sonnet-4-5-20250929",
584+
});
585+
586+
// Basic usage - enable all tools from an MCP server
587+
const response = await llm.invoke("What tools do you have available?", {
588+
mcp_servers: [
589+
{
590+
type: "url",
591+
url: "https://example-server.modelcontextprotocol.io/sse",
592+
name: "example-mcp",
593+
authorization_token: "YOUR_TOKEN",
594+
},
595+
],
596+
tools: [tools.mcpToolset_20251120({ serverName: "example-mcp" })],
597+
});
598+
```
599+
600+
**Allowlist pattern** - Enable only specific tools:
601+
602+
```typescript
603+
const response = await llm.invoke("Search for events", {
604+
mcp_servers: [
605+
{
606+
type: "url",
607+
url: "https://calendar.example.com/sse",
608+
name: "google-calendar-mcp",
609+
authorization_token: "YOUR_TOKEN",
610+
},
611+
],
612+
tools: [
613+
tools.mcpToolset_20251120({
614+
serverName: "google-calendar-mcp",
615+
// Disable all tools by default
616+
defaultConfig: { enabled: false },
617+
// Explicitly enable only these tools
618+
configs: {
619+
search_events: { enabled: true },
620+
create_event: { enabled: true },
621+
},
622+
}),
623+
],
624+
});
625+
```
626+
627+
**Denylist pattern** - Disable specific tools:
628+
629+
```typescript
630+
const response = await llm.invoke("List my events", {
631+
mcp_servers: [
632+
{
633+
type: "url",
634+
url: "https://calendar.example.com/sse",
635+
name: "google-calendar-mcp",
636+
authorization_token: "YOUR_TOKEN",
637+
},
638+
],
639+
tools: [
640+
tools.mcpToolset_20251120({
641+
serverName: "google-calendar-mcp",
642+
// All tools enabled by default, just disable dangerous ones
643+
configs: {
644+
delete_all_events: { enabled: false },
645+
share_calendar_publicly: { enabled: false },
646+
},
647+
}),
648+
],
649+
});
650+
```
651+
652+
**Multiple MCP servers**:
653+
654+
```typescript
655+
const response = await llm.invoke("Use tools from both servers", {
656+
mcp_servers: [
657+
{
658+
type: "url",
659+
url: "https://mcp.example1.com/sse",
660+
name: "mcp-server-1",
661+
authorization_token: "TOKEN1",
662+
},
663+
{
664+
type: "url",
665+
url: "https://mcp.example2.com/sse",
666+
name: "mcp-server-2",
667+
authorization_token: "TOKEN2",
668+
},
669+
],
670+
tools: [
671+
tools.mcpToolset_20251120({ serverName: "mcp-server-1" }),
672+
tools.mcpToolset_20251120({
673+
serverName: "mcp-server-2",
674+
defaultConfig: { deferLoading: true },
675+
}),
676+
],
677+
});
678+
```
679+
680+
**With Tool Search** - Use deferred loading for on-demand tool discovery:
681+
682+
```typescript
683+
const response = await llm.invoke("Find and use the right tool", {
684+
mcp_servers: [
685+
{
686+
type: "url",
687+
url: "https://example.com/sse",
688+
name: "example-mcp",
689+
},
690+
],
691+
tools: [
692+
tools.toolSearchRegex_20251119(),
693+
tools.mcpToolset_20251120({
694+
serverName: "example-mcp",
695+
defaultConfig: { deferLoading: true },
696+
}),
697+
],
698+
});
699+
```
700+
701+
For more information, see [Anthropic's MCP Connector documentation](https://docs.anthropic.com/en/docs/agents-and-tools/mcp-connector).
702+
566703
## Development
567704

568705
To develop the Anthropic package, you'll need to follow these instructions:

libs/providers/langchain-anthropic/src/chat_models.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import {
5757
AnthropicToolChoice,
5858
ChatAnthropicOutputFormat,
5959
ChatAnthropicToolType,
60+
AnthropicMCPServerURLDefinition,
6061
Kwargs,
6162
} from "./types.js";
6263
import { wrapAnthropicClientError } from "./utils/errors.js";
@@ -115,6 +116,10 @@ export interface ChatAnthropicCallOptions
115116
* See https://docs.anthropic.com/en/api/versioning for available beta features.
116117
*/
117118
betas?: AnthropicBeta[];
119+
/**
120+
* Array of MCP server URLs to use for the request.
121+
*/
122+
mcp_servers?: AnthropicMCPServerURLDefinition[];
118123
}
119124

120125
function _toolsInParams(

libs/providers/langchain-anthropic/src/tools/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { textEditor_20250728 } from "./textEditor.js";
99
import { computer_20251124, computer_20250124 } from "./computer.js";
1010
import { codeExecution_20250825 } from "./codeExecution.js";
1111
import { bash_20250124 } from "./bash.js";
12+
import { mcpToolset_20251120 } from "./mcpToolset.js";
1213

1314
export const tools = {
1415
memory_20250818,
@@ -21,6 +22,7 @@ export const tools = {
2122
computer_20250124,
2223
codeExecution_20250825,
2324
bash_20250124,
25+
mcpToolset_20251120,
2426
};
2527

2628
export type * from "./types.js";
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
import Anthropic from "@anthropic-ai/sdk";
2+
3+
/**
4+
* Configuration for a single tool in the MCP toolset.
5+
*/
6+
export interface MCPToolConfig {
7+
/**
8+
* Whether this tool is enabled.
9+
* @default true
10+
*/
11+
enabled?: boolean;
12+
/**
13+
* If true, tool description is not sent to the model initially.
14+
* Used with Tool Search Tool for on-demand loading.
15+
* @default false
16+
*/
17+
deferLoading?: boolean;
18+
}
19+
20+
/**
21+
* Per-tool configuration overrides.
22+
* Keys are tool names, values are configuration objects.
23+
*/
24+
export type MCPToolConfigs = Record<string, MCPToolConfig>;
25+
26+
/**
27+
* Options for creating an MCP toolset.
28+
*/
29+
export interface MCPToolsetOptions {
30+
/**
31+
* Must match a server name defined in the `mcp_servers` array in call options.
32+
*/
33+
serverName: string;
34+
/**
35+
* Default configuration applied to all tools in this toolset.
36+
* Individual tool configs will override these defaults.
37+
*/
38+
defaultConfig?: MCPToolConfig;
39+
/**
40+
* Per-tool configuration overrides.
41+
* Keys are tool names, values are configuration objects.
42+
*/
43+
configs?: MCPToolConfigs;
44+
/**
45+
* Create a cache control breakpoint at this content block.
46+
*/
47+
cacheControl?: Anthropic.Beta.BetaCacheControlEphemeral;
48+
}
49+
50+
/**
51+
* MCP toolset definition type.
52+
*/
53+
export interface MCPToolset {
54+
type: "mcp_toolset";
55+
mcp_server_name: string;
56+
default_config?: {
57+
enabled?: boolean;
58+
defer_loading?: boolean;
59+
};
60+
configs?: Record<
61+
string,
62+
{
63+
enabled?: boolean;
64+
defer_loading?: boolean;
65+
}
66+
>;
67+
cache_control?: Anthropic.Beta.BetaCacheControlEphemeral;
68+
}
69+
70+
/**
71+
* Creates an MCP toolset that connects to a remote MCP server to access its tools.
72+
* This enables Claude to use tools from MCP servers without implementing a separate MCP client.
73+
*
74+
* @note This tool requires the beta header `mcp-client-2025-11-20` in API requests.
75+
* The header is automatically added when using this tool.
76+
*
77+
* @see {@link https://docs.anthropic.com/en/docs/agents-and-tools/mcp-connector | Anthropic MCP Connector Documentation}
78+
* @param options - Configuration options for the MCP toolset
79+
* @returns An MCP toolset definition to be passed to the Anthropic API tools array
80+
*
81+
* @example
82+
* ```typescript
83+
* import { ChatAnthropic, tools } from "@langchain/anthropic";
84+
*
85+
* const model = new ChatAnthropic({
86+
* model: "claude-sonnet-4-5-20250929",
87+
* });
88+
*
89+
* // Basic usage - enable all tools from an MCP server
90+
* const response = await model.invoke("What tools do you have available?", {
91+
* mcp_servers: [{
92+
* type: "url",
93+
* url: "https://example-server.modelcontextprotocol.io/sse",
94+
* name: "example-mcp",
95+
* authorization_token: "YOUR_TOKEN",
96+
* }],
97+
* tools: [
98+
* tools.mcpToolset_20251120({ serverName: "example-mcp" }),
99+
* ],
100+
* });
101+
*
102+
* // Allowlist pattern - enable only specific tools
103+
* const responseAllowlist = await model.invoke("Search for events", {
104+
* mcp_servers: [{
105+
* type: "url",
106+
* url: "https://calendar.example.com/sse",
107+
* name: "google-calendar-mcp",
108+
* authorization_token: "YOUR_TOKEN",
109+
* }],
110+
* tools: [
111+
* tools.mcpToolset_20251120({
112+
* serverName: "google-calendar-mcp",
113+
* defaultConfig: { enabled: false },
114+
* configs: {
115+
* search_events: { enabled: true },
116+
* create_event: { enabled: true },
117+
* },
118+
* }),
119+
* ],
120+
* });
121+
*
122+
* // Denylist pattern - disable specific tools
123+
* const responseDenylist = await model.invoke("List my events", {
124+
* mcp_servers: [{
125+
* type: "url",
126+
* url: "https://calendar.example.com/sse",
127+
* name: "google-calendar-mcp",
128+
* authorization_token: "YOUR_TOKEN",
129+
* }],
130+
* tools: [
131+
* tools.mcpToolset_20251120({
132+
* serverName: "google-calendar-mcp",
133+
* configs: {
134+
* delete_all_events: { enabled: false },
135+
* share_calendar_publicly: { enabled: false },
136+
* },
137+
* }),
138+
* ],
139+
* });
140+
*
141+
* // With deferred loading for use with Tool Search Tool
142+
* const responseDeferred = await model.invoke("Search for tools", {
143+
* mcp_servers: [{
144+
* type: "url",
145+
* url: "https://example.com/sse",
146+
* name: "example-mcp",
147+
* }],
148+
* tools: [
149+
* tools.toolSearchRegex_20251119(),
150+
* tools.mcpToolset_20251120({
151+
* serverName: "example-mcp",
152+
* defaultConfig: { deferLoading: true },
153+
* }),
154+
* ],
155+
* });
156+
* ```
157+
*/
158+
export function mcpToolset_20251120(options: MCPToolsetOptions): MCPToolset {
159+
const defaultConfig =
160+
options.defaultConfig?.enabled !== undefined ||
161+
options.defaultConfig?.deferLoading !== undefined
162+
? {
163+
enabled: options.defaultConfig?.enabled,
164+
defer_loading: options.defaultConfig?.deferLoading,
165+
}
166+
: undefined;
167+
168+
const configs = options.configs
169+
? Object.fromEntries(
170+
Object.entries(options.configs).map(([toolName, config]) => [
171+
toolName,
172+
{
173+
enabled: config.enabled,
174+
defer_loading: config.deferLoading,
175+
},
176+
])
177+
)
178+
: undefined;
179+
180+
return {
181+
type: "mcp_toolset",
182+
mcp_server_name: options.serverName,
183+
default_config: defaultConfig,
184+
configs,
185+
cache_control: options.cacheControl,
186+
};
187+
}

0 commit comments

Comments
 (0)