Skip to content

Commit 5489217

Browse files
cyrus2281enavitan
andauthored
feat(DATAGO-118651): Add MCP Server Gateway Adapter plugin (#76)
* Add plugin for MCP Server Gateway Adapter - Implemented `sanitize_tool_name` to create valid MCP tool names. - Added `format_agent_skill_description` for generating human-readable skill descriptions. - Created `truncate_text` to limit text length with ellipsis. - Developed `create_session_id` for generating unique session IDs. - Introduced `extract_agent_skill_from_tool_name` to parse tool names into agent and skill components. - Added `should_include_tool` to filter tools based on include/exclude patterns. - Implemented helper functions `_split_patterns`, `_matches_exact_any`, and `_matches_regex_any` for pattern matching. * refactor: update README and pyproject.toml for clarity; enhance adapter cleanup methods * docs: update README and config.yaml to clarify tool filtering options * docs: update README and config.yaml to use regex for tool inclusion * feat: implement user access validation for agents and add middleware for tool filtering * refactor: remove triple-redirect OAuth flow references and update proxy URL handling * feat: add httpx dependency and implement refresh token handling in MCP OAuth flow * feat: update refresh token endpoint to include provider in request payload * feat: Implement OAuth 2.0 authorization flow with PKCE support - Added McpAdapterAuthHandler to manage OAuth 2.0 authorization, callback, and token exchange. - Introduced McpAdapterConfig for configuration management, including OAuth settings. - Created ListingFilterMiddleware to filter tools based on user permissions and access. - Implemented dynamic client registration and metadata endpoints for OAuth. - Added cleanup mechanisms for expired OAuth codes and states to prevent memory leaks. - Enhanced logging for better traceability of OAuth operations and user access filtering. * fix singleton mcp_context sharing * update mcp_oauth_callback as env var for cloud support * force MCP_EXTERNAL_URI for mcp card * force redirect_url from mcp to avoid falling on default value in prod/stag/beta * incorporate revew comments --------- Co-authored-by: Eugene N <eugene.navitaniuc@solace.com>
1 parent 58d1215 commit 5489217

File tree

9 files changed

+3251
-0
lines changed

9 files changed

+3251
-0
lines changed

sam-mcp-server-gateway-adapter/README.md

Lines changed: 430 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# MCP Gateway Example Configuration
2+
# This gateway exposes SAM agents as MCP (Model Context Protocol) tools.
3+
#
4+
# This allows any MCP-compatible client (like Claude Desktop, IDEs, etc.) to interact
5+
# with SAM agents through the standardized MCP interface.
6+
#
7+
# Features:
8+
# - Dynamic tool registration from agent registry
9+
# - HTTP or stdio transport support
10+
# - Streaming responses to MCP clients
11+
# - Timeout protection
12+
#
13+
# Required Environment Variables:
14+
# - NAMESPACE: The A2A topic namespace (e.g., "myorg/dev")
15+
# - SOLACE_BROKER_URL: URL of the Solace broker (e.g., "ws://localhost:8008")
16+
# - SOLACE_BROKER_USERNAME: Username for the Solace broker
17+
# - SOLACE_BROKER_PASSWORD: Password for the Solace broker
18+
# - SOLACE_BROKER_VPN: VPN name for the Solace broker
19+
#
20+
# Dependencies:
21+
# First install the sam-mcp-server-gateway-adapter plugin
22+
# > sam plugin install sam-mcp-server-gateway-adapter
23+
#
24+
# Usage:
25+
# sam run examples/gateways/mcp_gateway_example.yaml
26+
#
27+
# Then connect an MCP client to: http://localhost:8000/mcp
28+
29+
log:
30+
stdout_log_level: INFO
31+
log_file_level: DEBUG
32+
log_file: __COMPONENT_KEBAB_CASE_NAME__.log
33+
34+
# To use the `shared_config.yaml` file, uncomment the following line and remove the `shared_config` section below.
35+
# !include ../shared_config.yaml
36+
37+
shared_config:
38+
- broker_connection: &broker_connection
39+
dev_mode: ${SOLACE_DEV_MODE, false}
40+
broker_url: ${SOLACE_BROKER_URL, ws://localhost:8008}
41+
broker_username: ${SOLACE_BROKER_USERNAME, default}
42+
broker_password: ${SOLACE_BROKER_PASSWORD, default}
43+
broker_vpn: ${SOLACE_BROKER_VPN, default}
44+
temporary_queue: ${USE_TEMPORARY_QUEUES, true}
45+
46+
apps:
47+
- name: __COMPONENT_PASCAL_CASE_NAME____app
48+
app_base_path: .
49+
app_module: solace_agent_mesh.gateway.generic.app
50+
51+
broker:
52+
<<: *broker_connection
53+
54+
app_config:
55+
# --- Required ---
56+
namespace: ${NAMESPACE}
57+
58+
# --- Generic Adapter Framework Config ---
59+
gateway_adapter: solace_agent_mesh.gateway.mcp.adapter.McpAdapter
60+
61+
# --- MCP Adapter Config ---
62+
adapter_config:
63+
# MCP server identity
64+
mcp_server_name: "SAM MCP Gateway"
65+
66+
# Transport configuration
67+
# Options: "http" or "stdio"
68+
# - http: Web-accessible MCP server for remote clients
69+
# - stdio: Local MCP server for desktop clients (like Claude Desktop)
70+
transport: http
71+
72+
# HTTP transport settings (only used if transport = "http")
73+
host: ${__COMPONENT_UPPER_SNAKE_CASE_NAME___MCP_HOST, localhost} # Listen on all interfaces
74+
port: ${__COMPONENT_UPPER_SNAKE_CASE_NAME___MCP_PORT, 8090} # MCP server port
75+
76+
# Authentication
77+
# Default user identity for MCP requests
78+
# In production, you might want to implement token-based auth
79+
default_user_identity: "sam_dev_user"
80+
81+
# Streaming configuration
82+
# Enable real-time streaming of agent responses back to MCP client
83+
stream_responses: true
84+
85+
# Timeout configuration
86+
# How long to wait for agent task completion before timing out (in seconds)
87+
task_timeout_seconds: 300 # 5 minutes default
88+
89+
# File handling configuration
90+
# These settings control when files are returned inline vs as resource links
91+
inline_image_max_bytes: 5242880 # 5MB - images larger than this become resource links
92+
inline_audio_max_bytes: 10485760 # 10MB - audio files larger than this become resource links
93+
inline_text_max_bytes: 1048576 # 1MB - text files larger than this become resource links
94+
inline_binary_max_bytes: 524288 # 512KB - binary files larger than this become resource links
95+
96+
# Artifact resource configuration
97+
# Enable exposing artifacts as MCP resources for separate download
98+
enable_artifact_resources: true
99+
resource_uri_prefix: "artifact" # URI format: artifact://session_id/filename
100+
101+
# Tool filtering configuration
102+
# Control which agent tools are exposed through the MCP server
103+
# Filters check against agent name, skill name, AND final tool name
104+
# Supports both regex patterns and exact string matches (auto-detected)
105+
#
106+
# Priority order (highest to lowest):
107+
# 1. Exclude exact match - if any exclude pattern matches exactly, reject
108+
# 2. Include exact match - if any include pattern matches exactly, accept
109+
# 3. Exclude regex match - if any exclude pattern matches as regex, reject
110+
# 4. Include regex match - if any include pattern matches as regex, accept
111+
# 5. Default - if include_tools is empty, accept all; otherwise reject
112+
#
113+
# Examples:
114+
# include_tools:
115+
# - ".*" # Include all tools that exclude filters allows
116+
# - "data_.*" # Regex: include tools starting with "data_"
117+
# - "fetch_user_info" # Exact: include this specific tool
118+
# exclude_tools:
119+
# - ".*_debug" # Regex: exclude tools ending with "_debug"
120+
# - "TestAgent" # Exact: exclude all tools from agent "TestAgent"
121+
# - "test_tool" # Exact: exclude this specific tool
122+
#
123+
include_tools: [] # Empty = include all tools (default)
124+
exclude_tools: [] # Empty = no exclusions (default)
125+
126+
# --- Artifact Service ---
127+
artifact_service:
128+
type: "filesystem"
129+
base_path: "/tmp/samv2"
130+
artifact_scope: "namespace"
131+
132+
# --- Optional with Defaults ---
133+
default_user_identity: "sam_dev_user"
134+
135+
# --- System Purpose ---
136+
system_purpose: >
137+
The system is an AI Chatbot with agentic capabilities.
138+
It will use the agents available to provide information,
139+
reasoning and general assistance for the users in this system.
140+
**Always return useful artifacts and files that you create to the user.**
141+
Provide a status update before each tool call.
142+
Your external name is Agent Mesh.
143+
144+
response_format: >
145+
Responses should be clear, concise, and professionally toned.
146+
Format responses to the user in Markdown using appropriate formatting.
147+
Note that the user is not able to access the internal artifacts of the system. You
148+
must return them, so if you create any files or artifacts, provide them to the user
149+
via the artifact_return embed.
150+
151+
# Notes on usage:
152+
# ---------------
153+
# 1. Agents are automatically discovered from the agent registry
154+
# 2. Each agent skill becomes an MCP tool named: {agent_name}_{skill_name}
155+
# 3. All tools accept a single "message" parameter (string)
156+
# 4. Responses are streamed back in real-time
157+
# 5. Connect MCP clients to: http://localhost:8000/mcp (for HTTP transport)
158+
#
159+
# Example MCP client usage (with MCP inspector CLI):
160+
# npx @modelcontextprotocol/inspector
161+
# Select Streamable HTTP for the transport type and enter the following for the url: http://localhost:8090/mcp
162+
#
163+
# Example connecting from Claude Desktop:
164+
# Add to Claude Desktop config (~/.config/claude/config.json):
165+
# {
166+
# "mcpServers": {
167+
# "sam": {
168+
# "url": "http://localhost:8090/mcp",
169+
# "transport": "http"
170+
# }
171+
# }
172+
# }
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[build-system]
2+
requires = ["hatchling"]
3+
build-backend = "hatchling.build"
4+
5+
[tool.hatch.metadata]
6+
allow-direct-references = true
7+
8+
[tool.sam_mcp_server_gateway_adapter.metadata]
9+
type = "gateway"
10+
11+
[project]
12+
name = "sam_mcp_server_gateway_adapter"
13+
version = "0.1.0"
14+
authors = [
15+
{ name="SolaceLabs", email="solacelabs@solace.com" },
16+
]
17+
description = "A gateway adapter to make SAM accessible as a MCP server"
18+
readme = "README.md"
19+
requires-python = ">=3.10"
20+
dependencies = [
21+
"fastmcp~=2.12.5",
22+
"starlette~=0.49.1",
23+
"httpx>=0.27.0",
24+
]
25+
26+
[tool.hatch.build.targets.wheel]
27+
packages = ["src/sam_mcp_server_gateway_adapter"]
28+
src-path = "src"
29+
30+
[tool.hatch.build.targets.wheel.force-include]
31+
"src/sam_mcp_server_gateway_adapter" = "sam_mcp_server_gateway_adapter/"
32+
"config.yaml" = "sam_mcp_server_gateway_adapter/config.yaml"
33+
"README.md" = "sam_mcp_server_gateway_adapter/README.md"
34+
"pyproject.toml" = "sam_mcp_server_gateway_adapter/pyproject.toml"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
"""
2+
MCP Gateway Adapter - Exposes SAM as an MCP Server.
3+
4+
This adapter uses FastMCP to create a Model Context Protocol server that dynamically
5+
exposes SAM agents and their skills as MCP tools.
6+
"""
7+
8+
from .adapter import McpAdapter
9+
10+
__all__ = ["McpAdapter"]

0 commit comments

Comments
 (0)