From df27fec7296e1839d164920c1e5345afc4c7fcfb Mon Sep 17 00:00:00 2001 From: Sam Crowder Date: Wed, 19 Nov 2025 21:19:47 -0800 Subject: [PATCH 1/4] docs page --- src/docs.json | 1 + src/langsmith/agent-builder-mcp-framework.mdx | 97 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 src/langsmith/agent-builder-mcp-framework.mdx diff --git a/src/docs.json b/src/docs.json index 341be676ba..ad9d8016eb 100644 --- a/src/docs.json +++ b/src/docs.json @@ -1345,6 +1345,7 @@ "langsmith/agent-builder", "langsmith/agent-builder-setup", "langsmith/agent-builder-tools", + "langsmith/agent-builder-mcp-framework", "langsmith/agent-builder-slack-app" ] }, diff --git a/src/langsmith/agent-builder-mcp-framework.mdx b/src/langsmith/agent-builder-mcp-framework.mdx new file mode 100644 index 0000000000..82d5cdacbf --- /dev/null +++ b/src/langsmith/agent-builder-mcp-framework.mdx @@ -0,0 +1,97 @@ +--- +title: LangSmith Tool Server +sidebarTitle: MCP Framework +mode: wide +--- + +The LangSmith Tool Server is our MCP Framework that powers the tools available in the LangSmith Agent Builder. This framework enables you to build and deploy custom tools that can be integrated with your agents. It provides a standardized way to create, deploy, and manage tools with built-in authentication and authorization. + +The PyPi package that defines the framework is available [here](https://pypi.org/project/langsmith-tool-server/). + +## Quick start + +Install the LangSmith Tool Server and LangChain CLI: + +```bash +pip install langsmith-tool-server +pip install langchain-cli-v2 +``` + +Create a new toolkit: + +```bash +langchain tools new my-toolkit +cd my-toolkit +``` + +This creates a toolkit with the following structure: + +``` +my-toolkit/ +├── pyproject.toml +├── toolkit.toml +└── my_toolkit/ + ├── __init__.py + ├── auth.py + └── tools/ + ├── __init__.py + └── ... +``` + +Define your tools using the `@tool` decorator: + +```python +from langsmith_tool_server import tool + +@tool +def hello(name: str) -> str: + """Greet someone by name.""" + return f"Hello, {name}!" + +@tool +def add(x: int, y: int) -> int: + """Add two numbers.""" + return x + y + +TOOLS = [hello, add] +``` + +Run the server: + +```bash +langchain tools serve +``` + +Your tool server will start on `http://localhost:8000`. + +## Adding OAuth authentication + +For tools that need to access third-party APIs (like Google, GitHub, Slack, etc.), you can use OAuth authentication: + +```python +from langsmith_tool_server import tool, Context +from google.oauth2.credentials import Credentials +from googleapiclient.discovery import build + +@tool( + auth_provider="google", + scopes=["https://www.googleapis.com/auth/gmail.readonly"], + integration="gmail" +) +async def read_emails(context: Context, max_results: int = 10) -> str: + """Read recent emails from Gmail. + + Args: + context: Authentication context with OAuth token + max_results: Maximum number of emails to retrieve + """ + credentials = Credentials(token=context.token) + service = build('gmail', 'v1', credentials=credentials) + # ... Gmail API calls + return f"Retrieved {max_results} emails" +``` + +Tools with `auth_provider` must: +- Have `context: Context` as the first parameter +- Specify at least one scope +- Use `context.token` to make authenticated API calls From 2283158ba38b826fb4e9880c7f63e86c4d92b9ed Mon Sep 17 00:00:00 2001 From: Sam Crowder Date: Wed, 19 Nov 2025 21:25:39 -0800 Subject: [PATCH 2/4] adsf --- src/langsmith/agent-builder-mcp-framework.mdx | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/langsmith/agent-builder-mcp-framework.mdx b/src/langsmith/agent-builder-mcp-framework.mdx index 82d5cdacbf..3c26a9323f 100644 --- a/src/langsmith/agent-builder-mcp-framework.mdx +++ b/src/langsmith/agent-builder-mcp-framework.mdx @@ -64,6 +64,41 @@ langchain tools serve Your tool server will start on `http://localhost:8000`. +## Simple client example + +Once your server is running, you can connect to it using the MCP Python client: + +```bash +pip install mcp +``` + +Here's a simple example that lists available tools and calls the `add` tool: + +```python +import asyncio +from mcp import ClientSession +from mcp.client.sse import sse_client + +async def main(): + # Connect to the local tool server + url = "http://localhost:8000/mcp/sse" + + async with sse_client(url=url) as streams: + async with ClientSession(streams[0], streams[1]) as session: + # Initialize the session + await session.initialize() + + # List available tools + tools = await session.list_tools() + print("Available tools:", tools) + + # Call the add tool + result = await session.call_tool("add", {"x": 5, "y": 3}) + print("Result:", result) + +asyncio.run(main()) +``` + ## Adding OAuth authentication For tools that need to access third-party APIs (like Google, GitHub, Slack, etc.), you can use OAuth authentication: From 00f3603c4034e91741164d693428521cb66027ae Mon Sep 17 00:00:00 2001 From: Sam Crowder Date: Wed, 19 Nov 2025 21:34:35 -0800 Subject: [PATCH 3/4] short, working example --- src/langsmith/agent-builder-mcp-framework.mdx | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/langsmith/agent-builder-mcp-framework.mdx b/src/langsmith/agent-builder-mcp-framework.mdx index 3c26a9323f..7283289208 100644 --- a/src/langsmith/agent-builder-mcp-framework.mdx +++ b/src/langsmith/agent-builder-mcp-framework.mdx @@ -76,25 +76,22 @@ Here's a simple example that lists available tools and calls the `add` tool: ```python import asyncio -from mcp import ClientSession -from mcp.client.sse import sse_client +import aiohttp -async def main(): - # Connect to the local tool server - url = "http://localhost:8000/mcp/sse" +async def mcp_request(url: str, method: str, params: dict = None): + async with aiohttp.ClientSession() as session: + payload = {"jsonrpc": "2.0", "method": method, "params": params or {}, "id": 1} + async with session.post(f"{url}/mcp", json=payload) as response: + return await response.json() - async with sse_client(url=url) as streams: - async with ClientSession(streams[0], streams[1]) as session: - # Initialize the session - await session.initialize() +async def main(): + url = "http://localhost:8000" - # List available tools - tools = await session.list_tools() - print("Available tools:", tools) + tools = await mcp_request(url, "tools/list") + print(f"Tools: {tools}") - # Call the add tool - result = await session.call_tool("add", {"x": 5, "y": 3}) - print("Result:", result) + result = await mcp_request(url, "tools/call", {"name": "add", "arguments": {"a": 5, "b": 3}}) + print(f"Result: {result}") asyncio.run(main()) ``` From 015bf238906f763b52b0c37964405b01619b3663 Mon Sep 17 00:00:00 2001 From: Sam Crowder Date: Wed, 19 Nov 2025 21:37:12 -0800 Subject: [PATCH 4/4] good enough for now --- src/langsmith/agent-builder-mcp-framework.mdx | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/langsmith/agent-builder-mcp-framework.mdx b/src/langsmith/agent-builder-mcp-framework.mdx index 7283289208..f54be11cc5 100644 --- a/src/langsmith/agent-builder-mcp-framework.mdx +++ b/src/langsmith/agent-builder-mcp-framework.mdx @@ -66,12 +66,6 @@ Your tool server will start on `http://localhost:8000`. ## Simple client example -Once your server is running, you can connect to it using the MCP Python client: - -```bash -pip install mcp -``` - Here's a simple example that lists available tools and calls the `add` tool: ```python @@ -98,7 +92,11 @@ asyncio.run(main()) ## Adding OAuth authentication -For tools that need to access third-party APIs (like Google, GitHub, Slack, etc.), you can use OAuth authentication: +For tools that need to access third-party APIs (like Google, GitHub, Slack, etc.), you can use OAuth authentication with [Agent Auth](/langsmith/agent-auth). + +Before using OAuth in your tools, you'll need to configure an OAuth provider in your LangSmith workspace settings. See the [Agent Auth documentation](/langsmith/agent-auth) for setup instructions. + +Once configured, specify the `auth_provider` in your tool decorator: ```python from langsmith_tool_server import tool, Context @@ -111,12 +109,7 @@ from googleapiclient.discovery import build integration="gmail" ) async def read_emails(context: Context, max_results: int = 10) -> str: - """Read recent emails from Gmail. - - Args: - context: Authentication context with OAuth token - max_results: Maximum number of emails to retrieve - """ + """Read recent emails from Gmail.""" credentials = Credentials(token=context.token) service = build('gmail', 'v1', credentials=credentials) # ... Gmail API calls