signalwire-agents 0.1.6__py3-none-any.whl → 1.0.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. signalwire_agents/__init__.py +130 -4
  2. signalwire_agents/agent_server.py +438 -32
  3. signalwire_agents/agents/bedrock.py +296 -0
  4. signalwire_agents/cli/__init__.py +18 -0
  5. signalwire_agents/cli/build_search.py +1367 -0
  6. signalwire_agents/cli/config.py +80 -0
  7. signalwire_agents/cli/core/__init__.py +10 -0
  8. signalwire_agents/cli/core/agent_loader.py +470 -0
  9. signalwire_agents/cli/core/argparse_helpers.py +179 -0
  10. signalwire_agents/cli/core/dynamic_config.py +71 -0
  11. signalwire_agents/cli/core/service_loader.py +303 -0
  12. signalwire_agents/cli/execution/__init__.py +10 -0
  13. signalwire_agents/cli/execution/datamap_exec.py +446 -0
  14. signalwire_agents/cli/execution/webhook_exec.py +134 -0
  15. signalwire_agents/cli/init_project.py +1225 -0
  16. signalwire_agents/cli/output/__init__.py +10 -0
  17. signalwire_agents/cli/output/output_formatter.py +255 -0
  18. signalwire_agents/cli/output/swml_dump.py +186 -0
  19. signalwire_agents/cli/simulation/__init__.py +10 -0
  20. signalwire_agents/cli/simulation/data_generation.py +374 -0
  21. signalwire_agents/cli/simulation/data_overrides.py +200 -0
  22. signalwire_agents/cli/simulation/mock_env.py +282 -0
  23. signalwire_agents/cli/swaig_test_wrapper.py +52 -0
  24. signalwire_agents/cli/test_swaig.py +809 -0
  25. signalwire_agents/cli/types.py +81 -0
  26. signalwire_agents/core/__init__.py +2 -2
  27. signalwire_agents/core/agent/__init__.py +12 -0
  28. signalwire_agents/core/agent/config/__init__.py +12 -0
  29. signalwire_agents/core/agent/deployment/__init__.py +9 -0
  30. signalwire_agents/core/agent/deployment/handlers/__init__.py +9 -0
  31. signalwire_agents/core/agent/prompt/__init__.py +14 -0
  32. signalwire_agents/core/agent/prompt/manager.py +306 -0
  33. signalwire_agents/core/agent/routing/__init__.py +9 -0
  34. signalwire_agents/core/agent/security/__init__.py +9 -0
  35. signalwire_agents/core/agent/swml/__init__.py +9 -0
  36. signalwire_agents/core/agent/tools/__init__.py +15 -0
  37. signalwire_agents/core/agent/tools/decorator.py +97 -0
  38. signalwire_agents/core/agent/tools/registry.py +210 -0
  39. signalwire_agents/core/agent_base.py +959 -2166
  40. signalwire_agents/core/auth_handler.py +233 -0
  41. signalwire_agents/core/config_loader.py +259 -0
  42. signalwire_agents/core/contexts.py +707 -0
  43. signalwire_agents/core/data_map.py +487 -0
  44. signalwire_agents/core/function_result.py +1150 -1
  45. signalwire_agents/core/logging_config.py +376 -0
  46. signalwire_agents/core/mixins/__init__.py +28 -0
  47. signalwire_agents/core/mixins/ai_config_mixin.py +442 -0
  48. signalwire_agents/core/mixins/auth_mixin.py +287 -0
  49. signalwire_agents/core/mixins/prompt_mixin.py +358 -0
  50. signalwire_agents/core/mixins/serverless_mixin.py +368 -0
  51. signalwire_agents/core/mixins/skill_mixin.py +55 -0
  52. signalwire_agents/core/mixins/state_mixin.py +153 -0
  53. signalwire_agents/core/mixins/tool_mixin.py +230 -0
  54. signalwire_agents/core/mixins/web_mixin.py +1134 -0
  55. signalwire_agents/core/security/session_manager.py +174 -86
  56. signalwire_agents/core/security_config.py +333 -0
  57. signalwire_agents/core/skill_base.py +200 -0
  58. signalwire_agents/core/skill_manager.py +244 -0
  59. signalwire_agents/core/swaig_function.py +33 -9
  60. signalwire_agents/core/swml_builder.py +212 -12
  61. signalwire_agents/core/swml_handler.py +43 -13
  62. signalwire_agents/core/swml_renderer.py +123 -297
  63. signalwire_agents/core/swml_service.py +277 -260
  64. signalwire_agents/prefabs/concierge.py +6 -2
  65. signalwire_agents/prefabs/info_gatherer.py +149 -33
  66. signalwire_agents/prefabs/receptionist.py +14 -22
  67. signalwire_agents/prefabs/survey.py +6 -2
  68. signalwire_agents/schema.json +9218 -5489
  69. signalwire_agents/search/__init__.py +137 -0
  70. signalwire_agents/search/document_processor.py +1223 -0
  71. signalwire_agents/search/index_builder.py +804 -0
  72. signalwire_agents/search/migration.py +418 -0
  73. signalwire_agents/search/models.py +30 -0
  74. signalwire_agents/search/pgvector_backend.py +752 -0
  75. signalwire_agents/search/query_processor.py +502 -0
  76. signalwire_agents/search/search_engine.py +1264 -0
  77. signalwire_agents/search/search_service.py +574 -0
  78. signalwire_agents/skills/README.md +452 -0
  79. signalwire_agents/skills/__init__.py +23 -0
  80. signalwire_agents/skills/api_ninjas_trivia/README.md +215 -0
  81. signalwire_agents/skills/api_ninjas_trivia/__init__.py +12 -0
  82. signalwire_agents/skills/api_ninjas_trivia/skill.py +237 -0
  83. signalwire_agents/skills/datasphere/README.md +210 -0
  84. signalwire_agents/skills/datasphere/__init__.py +12 -0
  85. signalwire_agents/skills/datasphere/skill.py +310 -0
  86. signalwire_agents/skills/datasphere_serverless/README.md +258 -0
  87. signalwire_agents/skills/datasphere_serverless/__init__.py +10 -0
  88. signalwire_agents/skills/datasphere_serverless/skill.py +237 -0
  89. signalwire_agents/skills/datetime/README.md +132 -0
  90. signalwire_agents/skills/datetime/__init__.py +10 -0
  91. signalwire_agents/skills/datetime/skill.py +126 -0
  92. signalwire_agents/skills/joke/README.md +149 -0
  93. signalwire_agents/skills/joke/__init__.py +10 -0
  94. signalwire_agents/skills/joke/skill.py +109 -0
  95. signalwire_agents/skills/math/README.md +161 -0
  96. signalwire_agents/skills/math/__init__.py +10 -0
  97. signalwire_agents/skills/math/skill.py +105 -0
  98. signalwire_agents/skills/mcp_gateway/README.md +230 -0
  99. signalwire_agents/skills/mcp_gateway/__init__.py +10 -0
  100. signalwire_agents/skills/mcp_gateway/skill.py +421 -0
  101. signalwire_agents/skills/native_vector_search/README.md +210 -0
  102. signalwire_agents/skills/native_vector_search/__init__.py +10 -0
  103. signalwire_agents/skills/native_vector_search/skill.py +820 -0
  104. signalwire_agents/skills/play_background_file/README.md +218 -0
  105. signalwire_agents/skills/play_background_file/__init__.py +12 -0
  106. signalwire_agents/skills/play_background_file/skill.py +242 -0
  107. signalwire_agents/skills/registry.py +459 -0
  108. signalwire_agents/skills/spider/README.md +236 -0
  109. signalwire_agents/skills/spider/__init__.py +13 -0
  110. signalwire_agents/skills/spider/skill.py +598 -0
  111. signalwire_agents/skills/swml_transfer/README.md +395 -0
  112. signalwire_agents/skills/swml_transfer/__init__.py +10 -0
  113. signalwire_agents/skills/swml_transfer/skill.py +359 -0
  114. signalwire_agents/skills/weather_api/README.md +178 -0
  115. signalwire_agents/skills/weather_api/__init__.py +12 -0
  116. signalwire_agents/skills/weather_api/skill.py +191 -0
  117. signalwire_agents/skills/web_search/README.md +163 -0
  118. signalwire_agents/skills/web_search/__init__.py +10 -0
  119. signalwire_agents/skills/web_search/skill.py +739 -0
  120. signalwire_agents/skills/wikipedia_search/README.md +228 -0
  121. signalwire_agents/{core/state → skills/wikipedia_search}/__init__.py +5 -4
  122. signalwire_agents/skills/wikipedia_search/skill.py +210 -0
  123. signalwire_agents/utils/__init__.py +14 -0
  124. signalwire_agents/utils/schema_utils.py +111 -44
  125. signalwire_agents/web/__init__.py +17 -0
  126. signalwire_agents/web/web_service.py +559 -0
  127. signalwire_agents-1.0.7.data/data/share/man/man1/sw-agent-init.1 +307 -0
  128. signalwire_agents-1.0.7.data/data/share/man/man1/sw-search.1 +483 -0
  129. signalwire_agents-1.0.7.data/data/share/man/man1/swaig-test.1 +308 -0
  130. signalwire_agents-1.0.7.dist-info/METADATA +992 -0
  131. signalwire_agents-1.0.7.dist-info/RECORD +142 -0
  132. {signalwire_agents-0.1.6.dist-info → signalwire_agents-1.0.7.dist-info}/WHEEL +1 -1
  133. signalwire_agents-1.0.7.dist-info/entry_points.txt +4 -0
  134. signalwire_agents/core/state/file_state_manager.py +0 -219
  135. signalwire_agents/core/state/state_manager.py +0 -101
  136. signalwire_agents-0.1.6.data/data/schema.json +0 -5611
  137. signalwire_agents-0.1.6.dist-info/METADATA +0 -199
  138. signalwire_agents-0.1.6.dist-info/RECORD +0 -34
  139. {signalwire_agents-0.1.6.dist-info → signalwire_agents-1.0.7.dist-info}/licenses/LICENSE +0 -0
  140. {signalwire_agents-0.1.6.dist-info → signalwire_agents-1.0.7.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,109 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
10
+ from typing import List, Dict, Any
11
+
12
+ from signalwire_agents.core.skill_base import SkillBase
13
+ from signalwire_agents.core.data_map import DataMap
14
+ from signalwire_agents.core.function_result import SwaigFunctionResult
15
+
16
+
17
+ class JokeSkill(SkillBase):
18
+ """Joke telling capability using API Ninjas with DataMap"""
19
+
20
+ SKILL_NAME = "joke"
21
+ SKILL_DESCRIPTION = "Tell jokes using the API Ninjas joke API"
22
+ SKILL_VERSION = "1.0.0"
23
+ REQUIRED_PACKAGES = [] # DataMap doesn't require local packages
24
+ REQUIRED_ENV_VARS = [] # API key comes from parameters
25
+
26
+ @classmethod
27
+ def get_parameter_schema(cls) -> Dict[str, Dict[str, Any]]:
28
+ """Get parameter schema for joke skill"""
29
+ schema = super().get_parameter_schema()
30
+ schema.update({
31
+ "api_key": {
32
+ "type": "string",
33
+ "description": "API Ninjas API key for joke service",
34
+ "required": True,
35
+ "hidden": True,
36
+ "env_var": "API_NINJAS_KEY"
37
+ },
38
+ "tool_name": {
39
+ "type": "string",
40
+ "description": "Custom name for the joke tool",
41
+ "default": "get_joke",
42
+ "required": False
43
+ }
44
+ })
45
+ return schema
46
+
47
+ def setup(self) -> bool:
48
+ """Setup the joke skill"""
49
+ # Validate required parameters
50
+ required_params = ['api_key']
51
+ missing_params = [param for param in required_params if not self.params.get(param)]
52
+ if missing_params:
53
+ self.logger.error(f"Missing required parameters: {missing_params}")
54
+ return False
55
+
56
+ # Set parameters from config
57
+ self.api_key = self.params['api_key']
58
+
59
+ # Optional parameters with defaults
60
+ self.tool_name = self.params.get('tool_name', 'get_joke')
61
+
62
+ return True
63
+
64
+ def register_tools(self) -> None:
65
+ """Register joke tool using DataMap"""
66
+
67
+ # Create DataMap tool for jokes - uses required enum parameter
68
+ joke_tool = (DataMap(self.tool_name)
69
+ .description('Get a random joke from API Ninjas')
70
+ .parameter('type', 'string', 'Type of joke to get',
71
+ required=True, enum=['jokes', 'dadjokes'])
72
+ .webhook('GET', "https://api.api-ninjas.com/v1/${args.type}",
73
+ headers={'X-Api-Key': self.api_key})
74
+ .output(SwaigFunctionResult('Here\'s a joke: ${array[0].joke}'))
75
+ .error_keys(['error'])
76
+ .fallback_output(SwaigFunctionResult('Sorry, there is a problem with the joke service right now. Please try again later.'))
77
+ )
78
+
79
+ # Register the DataMap tool with the agent
80
+ self.agent.register_swaig_function(joke_tool.to_swaig_function())
81
+
82
+ def get_hints(self) -> List[str]:
83
+ """Return speech recognition hints"""
84
+ # Currently no hints are provided, but you could add them like:
85
+ # return [
86
+ # "joke", "tell me a joke", "funny", "humor", "dad joke",
87
+ # "regular joke", "make me laugh", "comedy"
88
+ # ]
89
+ return []
90
+
91
+ def get_global_data(self) -> Dict[str, Any]:
92
+ """Return global data to be available in DataMap variables"""
93
+ return {
94
+ "joke_skill_enabled": True
95
+ }
96
+
97
+ def get_prompt_sections(self) -> List[Dict[str, Any]]:
98
+ """Return prompt sections to add to agent"""
99
+ return [
100
+ {
101
+ "title": "Joke Telling",
102
+ "body": "You can tell jokes to entertain users.",
103
+ "bullets": [
104
+ f"Use {self.tool_name} to tell jokes when users ask for humor",
105
+ "You can tell regular jokes or dad jokes",
106
+ "Be enthusiastic and fun when sharing jokes"
107
+ ]
108
+ }
109
+ ]
@@ -0,0 +1,161 @@
1
+ # Math Skill
2
+
3
+ The math skill provides safe mathematical calculation capabilities for agents. It allows users to perform basic arithmetic operations and complex mathematical expressions with security protections against code injection.
4
+
5
+ ## Features
6
+
7
+ - Safe mathematical expression evaluation
8
+ - Support for basic arithmetic operations
9
+ - Parentheses support for complex expressions
10
+ - Division by zero protection
11
+ - Security filtering to prevent code injection
12
+ - No external dependencies required
13
+
14
+ ## Requirements
15
+
16
+ - **Packages**: None (uses built-in Python functionality)
17
+ - **No external APIs required**
18
+
19
+ ## Parameters
20
+
21
+ ### Optional Parameters
22
+
23
+ - `swaig_fields` (dict): Additional SWAIG function configuration
24
+ - `secure` (boolean): Override security settings for the calculation function
25
+ - `fillers` (dict): Language-specific filler phrases while calculating
26
+ - Any other SWAIG function parameters
27
+
28
+ **Note**: This skill does not require any configuration parameters beyond the optional swaig_fields. It works out-of-the-box with no setup.
29
+
30
+ ## Tools Created
31
+
32
+ - `calculate` - Perform a mathematical calculation with basic operations
33
+
34
+ ## Usage Examples
35
+
36
+ ### Basic Usage
37
+
38
+ ```python
39
+ # No configuration needed - works immediately
40
+ agent.add_skill("math")
41
+ ```
42
+
43
+ ### With Custom Fillers
44
+
45
+ ```python
46
+ agent.add_skill("math", {
47
+ "swaig_fields": {
48
+ "fillers": {
49
+ "en-US": [
50
+ "Let me calculate that for you...",
51
+ "Crunching the numbers...",
52
+ "Computing the result...",
53
+ "Working out the math..."
54
+ ],
55
+ "es-ES": [
56
+ "Déjame calcular eso...",
57
+ "Procesando los números...",
58
+ "Calculando el resultado..."
59
+ ]
60
+ }
61
+ }
62
+ })
63
+ ```
64
+
65
+ ### Disabling Security (if needed)
66
+
67
+ ```python
68
+ agent.add_skill("math", {
69
+ "swaig_fields": {
70
+ "secure": False # Allow unauthenticated calculation requests
71
+ }
72
+ })
73
+ ```
74
+
75
+ ## How It Works
76
+
77
+ ### Calculation Function
78
+ - **Input**: Mathematical expression as a string
79
+ - **Processing**: Validates expression for safety, then evaluates it
80
+ - **Output**: Shows the original expression and the calculated result
81
+ - **Example**: "2 + 3 * 4 = 14"
82
+
83
+ ### Supported Operations
84
+
85
+ - **Addition**: `+` (e.g., "5 + 3")
86
+ - **Subtraction**: `-` (e.g., "10 - 7")
87
+ - **Multiplication**: `*` (e.g., "6 * 8")
88
+ - **Division**: `/` (e.g., "15 / 3")
89
+ - **Modulo**: `%` (e.g., "17 % 5")
90
+ - **Exponentiation**: `**` (e.g., "2 ** 3")
91
+ - **Parentheses**: `()` for grouping (e.g., "(2 + 3) * 4")
92
+
93
+ ### Expression Examples
94
+
95
+ - Simple: `"2 + 3"` → "2 + 3 = 5"
96
+ - Complex: `"(10 + 5) * 2 / 3"` → "(10 + 5) * 2 / 3 = 10.0"
97
+ - With decimals: `"3.14 * 2"` → "3.14 * 2 = 6.28"
98
+ - Powers: `"2 ** 8"` → "2 ** 8 = 256"
99
+ - Modulo: `"17 % 5"` → "17 % 5 = 2"
100
+
101
+ ## Function Parameters
102
+
103
+ The calculate tool accepts one parameter:
104
+
105
+ - `expression` (string, required): Mathematical expression to evaluate
106
+ - Must contain only numbers, operators, and parentheses
107
+ - Operators allowed: `+`, `-`, `*`, `/`, `%`, `**`, `(`, `)`
108
+ - Decimal numbers are supported
109
+ - Spaces are allowed and ignored
110
+
111
+ ## Security Features
112
+
113
+ ### Input Validation
114
+ - Only allows safe mathematical characters: numbers, operators, parentheses, spaces, decimal points
115
+ - Blocks any potentially dangerous code or function calls
116
+ - Uses regex pattern matching for character validation
117
+
118
+ ### Safe Evaluation
119
+ - Uses Python's `eval()` with restricted builtins (empty `__builtins__`)
120
+ - No access to system functions or imports
121
+ - Cannot execute arbitrary code
122
+
123
+ ### Error Handling
124
+ - **Division by Zero**: Returns friendly error message
125
+ - **Invalid Syntax**: Returns error for malformed expressions
126
+ - **Illegal Characters**: Rejects expressions with non-math characters
127
+ - **Empty Input**: Prompts user to provide an expression
128
+
129
+ ## Error Examples
130
+
131
+ - **Division by zero**: "Error: Division by zero is not allowed."
132
+ - **Invalid characters**: "Invalid expression. Only numbers and basic math operators are allowed."
133
+ - **Syntax error**: "Error calculating '2 + + 3': Invalid expression"
134
+ - **Empty input**: "Please provide a mathematical expression to calculate."
135
+
136
+ ## Common Use Cases
137
+
138
+ 1. **Basic Arithmetic**: "What's 15 + 27?"
139
+ 2. **Percentage Calculations**: "What's 15% of 200?" → "200 * 0.15"
140
+ 3. **Complex Expressions**: "Calculate (100 + 50) * 0.08"
141
+ 4. **Powers and Roots**: "What's 2 to the power of 10?"
142
+ 5. **Financial Calculations**: "If I have $500 and spend $125, how much is left?"
143
+
144
+ ## Best Practices
145
+
146
+ 1. **Default Behavior**: The skill works immediately without configuration
147
+ 2. **User Education**: Help users understand they can use parentheses for complex calculations
148
+ 3. **Expression Formatting**: The skill is forgiving with spaces and formatting
149
+ 4. **Error Recovery**: Provide helpful guidance when users make syntax errors
150
+ 5. **Security**: The skill is designed to be safe even with malicious input
151
+
152
+ ## Agent Integration
153
+
154
+ When added to an agent, this skill automatically:
155
+
156
+ - Adds speech recognition hints for math-related words
157
+ - Provides prompt guidance about calculation capabilities
158
+ - Enables the agent to respond to mathematical questions
159
+ - Shows both the original expression and result for transparency
160
+
161
+ The skill is designed to be completely self-contained and secure, making it safe for any agent to use for mathematical calculations.
@@ -0,0 +1,10 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
10
+ """Math Skill for SignalWire Agents"""
@@ -0,0 +1,105 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
10
+ import re
11
+ from typing import List, Dict, Any
12
+
13
+ from signalwire_agents.core.skill_base import SkillBase
14
+ from signalwire_agents.core.function_result import SwaigFunctionResult
15
+
16
+ class MathSkill(SkillBase):
17
+ """Provides basic mathematical calculation capabilities"""
18
+
19
+ SKILL_NAME = "math"
20
+ SKILL_DESCRIPTION = "Perform basic mathematical calculations"
21
+ SKILL_VERSION = "1.0.0"
22
+ REQUIRED_PACKAGES = []
23
+ REQUIRED_ENV_VARS = []
24
+
25
+ def setup(self) -> bool:
26
+ """Setup the math skill"""
27
+ return True
28
+
29
+ def register_tools(self) -> None:
30
+ """Register math tools with the agent"""
31
+
32
+ self.define_tool(
33
+ name="calculate",
34
+ description="Perform a mathematical calculation with basic operations (+, -, *, /, %, **)",
35
+ parameters={
36
+ "expression": {
37
+ "type": "string",
38
+ "description": "Mathematical expression to evaluate (e.g., '2 + 3 * 4', '(10 + 5) / 3')"
39
+ }
40
+ },
41
+ handler=self._calculate_handler
42
+ )
43
+
44
+ def _calculate_handler(self, args, raw_data):
45
+ """Handler for calculate tool"""
46
+ expression = args.get("expression", "").strip()
47
+
48
+ if not expression:
49
+ return SwaigFunctionResult("Please provide a mathematical expression to calculate.")
50
+
51
+ # Security: only allow safe mathematical operations
52
+ safe_chars = re.compile(r'^[0-9+\-*/().\s%**]+$')
53
+ if not safe_chars.match(expression):
54
+ return SwaigFunctionResult(
55
+ "Invalid expression. Only numbers and basic math operators (+, -, *, /, %, **, parentheses) are allowed."
56
+ )
57
+
58
+ try:
59
+ # Evaluate the expression safely
60
+ result = eval(expression, {"__builtins__": {}}, {})
61
+
62
+ return SwaigFunctionResult(f"{expression} = {result}")
63
+
64
+ except ZeroDivisionError:
65
+ return SwaigFunctionResult("Error: Division by zero is not allowed.")
66
+ except Exception as e:
67
+ return SwaigFunctionResult(f"Error calculating '{expression}': Invalid expression")
68
+
69
+ def get_hints(self) -> List[str]:
70
+ """Return speech recognition hints"""
71
+ # Currently no hints provided, but you could add them like:
72
+ # return [
73
+ # "calculate", "math", "plus", "minus", "times", "multiply",
74
+ # "divide", "equals", "percent", "power", "squared"
75
+ # ]
76
+ return []
77
+
78
+ def get_prompt_sections(self) -> List[Dict[str, Any]]:
79
+ """Return prompt sections to add to agent"""
80
+ return [
81
+ {
82
+ "title": "Mathematical Calculations",
83
+ "body": "You can perform mathematical calculations for users.",
84
+ "bullets": [
85
+ "Use the calculate tool for any math expressions",
86
+ "Supports basic operations: +, -, *, /, %, ** (power)",
87
+ "Can handle parentheses for complex expressions"
88
+ ]
89
+ }
90
+ ]
91
+
92
+ @classmethod
93
+ def get_parameter_schema(cls) -> Dict[str, Dict[str, Any]]:
94
+ """
95
+ Get the parameter schema for the math skill
96
+
97
+ The math skill has no custom parameters - it inherits only
98
+ the base parameters from SkillBase.
99
+ """
100
+ # Get base schema from parent
101
+ schema = super().get_parameter_schema()
102
+
103
+ # No additional parameters for math skill
104
+
105
+ return schema
@@ -0,0 +1,230 @@
1
+ # MCP Gateway Skill
2
+
3
+ Bridge MCP (Model Context Protocol) servers with SignalWire SWAIG functions, allowing agents to seamlessly interact with MCP-based tools.
4
+
5
+ ## Description
6
+
7
+ The MCP Gateway skill connects SignalWire agents to MCP servers through a centralized gateway service. It dynamically discovers and registers MCP tools as SWAIG functions, maintaining session state throughout each call.
8
+
9
+ ## Features
10
+
11
+ - Dynamic tool discovery from MCP servers
12
+ - Session management tied to SignalWire call IDs
13
+ - Automatic cleanup on call hangup
14
+ - Support for multiple MCP services
15
+ - Selective tool loading
16
+ - HTTPS support with SSL verification
17
+ - Retry logic for resilient connections
18
+
19
+ ## Requirements
20
+
21
+ - Running MCP Gateway service
22
+ - Network access to gateway
23
+ - Gateway credentials (username/password)
24
+
25
+ ## Configuration
26
+
27
+ ### Required Parameters
28
+
29
+ Either Basic Auth credentials OR Bearer token:
30
+ - `gateway_url`: URL of the MCP gateway service (default: "http://localhost:8100")
31
+ - `auth_user` + `auth_password`: Basic auth credentials
32
+ - OR `auth_token`: Bearer token for authentication
33
+
34
+ ### Optional Parameters
35
+
36
+ - `services`: Array of services to load (default: all available)
37
+ - `name`: Service name
38
+ - `tools`: Array of tool names or "*" for all (default: all)
39
+ - `session_timeout`: Session timeout in seconds (default: 300)
40
+ - `tool_prefix`: Prefix for SWAIG function names (default: "mcp_")
41
+ - `retry_attempts`: Number of retry attempts (default: 3)
42
+ - `request_timeout`: HTTP request timeout in seconds (default: 30)
43
+ - `verify_ssl`: Verify SSL certificates (default: true)
44
+
45
+ ## Usage
46
+
47
+ ### Basic Usage (All Services)
48
+
49
+ ```python
50
+ from signalwire_agents import AgentBase
51
+
52
+ class MyAgent(AgentBase):
53
+ def __init__(self):
54
+ super().__init__(name="My Agent")
55
+
56
+ # Load all available MCP services
57
+ self.add_skill("mcp_gateway", {
58
+ "gateway_url": "http://localhost:8080",
59
+ "auth_user": "admin",
60
+ "auth_password": "changeme"
61
+ })
62
+
63
+ agent = MyAgent()
64
+ agent.run()
65
+ ```
66
+
67
+ ### Selective Service Loading
68
+
69
+ ```python
70
+ # Load specific services with specific tools
71
+ self.add_skill("mcp_gateway", {
72
+ "gateway_url": "https://gateway.example.com",
73
+ "auth_user": "admin",
74
+ "auth_password": "secret",
75
+ "services": [
76
+ {
77
+ "name": "todo",
78
+ "tools": ["add_todo", "list_todos"] # Only these tools
79
+ },
80
+ {
81
+ "name": "calculator",
82
+ "tools": "*" # All calculator tools
83
+ }
84
+ ],
85
+ "session_timeout": 600,
86
+ "tool_prefix": "ext_"
87
+ })
88
+ ```
89
+
90
+ ### HTTPS with Self-Signed Certificate
91
+
92
+ ```python
93
+ self.add_skill("mcp_gateway", {
94
+ "gateway_url": "https://localhost:8443",
95
+ "auth_user": "admin",
96
+ "auth_password": "secret",
97
+ "verify_ssl": False # For self-signed certificates
98
+ })
99
+ ```
100
+
101
+ ### Bearer Token Authentication
102
+
103
+ ```python
104
+ self.add_skill("mcp_gateway", {
105
+ "gateway_url": "https://gateway.example.com",
106
+ "auth_token": "your-bearer-token-here",
107
+ "services": [{
108
+ "name": "todo"
109
+ }]
110
+ })
111
+ ```
112
+
113
+ ## Generated Functions
114
+
115
+ The skill dynamically generates SWAIG functions based on discovered MCP tools. Function names follow the pattern:
116
+
117
+ `{tool_prefix}{service_name}_{tool_name}`
118
+
119
+ For example, with default settings:
120
+ - `mcp_todo_add_todo` - Add a todo item
121
+ - `mcp_todo_list_todos` - List todo items
122
+ - `mcp_calculator_add` - Calculator addition
123
+
124
+ ## Example Conversations
125
+
126
+ ### Using Todo Service
127
+
128
+ ```
129
+ User: "Add a task to buy milk"
130
+ Assistant: "I'll add that to your todo list."
131
+ [Calls mcp_todo_add_todo with text="buy milk"]
132
+ Assistant: "I've added 'buy milk' to your todo list."
133
+
134
+ User: "What's on my todo list?"
135
+ Assistant: "Let me check your todos."
136
+ [Calls mcp_todo_list_todos]
137
+ Assistant: "Here are your current todos:
138
+ ○ #1 [medium] buy milk"
139
+ ```
140
+
141
+ ### Multiple Services
142
+
143
+ ```
144
+ User: "Add 'finish report' to my todos and calculate 15% of 200"
145
+ Assistant: "I'll add that todo and do the calculation for you."
146
+ [Calls mcp_todo_add_todo with text="finish report"]
147
+ [Calls mcp_calculator_percent with value=200, percent=15]
148
+ Assistant: "I've added 'finish report' to your todos. 15% of 200 is 30."
149
+ ```
150
+
151
+ ## Session Management
152
+
153
+ - Each SignalWire call gets its own MCP session
154
+ - Sessions persist across multiple tool calls
155
+ - Automatic cleanup on call hangup
156
+ - Configurable timeout for inactive sessions
157
+
158
+ ### Custom Session ID
159
+
160
+ You can override the session ID by setting `mcp_call_id` in global_data:
161
+
162
+ ```python
163
+ # In your agent code
164
+ self.set_global_data({
165
+ "mcp_call_id": "custom-session-123"
166
+ })
167
+
168
+ # Or in a SWAIG function
169
+ result = SwaigFunctionResult("Session changed")
170
+ result.add_action("set_global_data", {"mcp_call_id": "new-session-456"})
171
+ ```
172
+
173
+ This is useful for:
174
+ - Managing multiple MCP sessions within a single call
175
+ - Sharing MCP sessions across different calls
176
+ - Custom session management strategies
177
+
178
+ ## Troubleshooting
179
+
180
+ ### Gateway Connection Failed
181
+
182
+ Check:
183
+ 1. Gateway service is running
184
+ 2. Correct URL and credentials
185
+ 3. Network connectivity
186
+ 4. Firewall rules
187
+
188
+ ### SSL Certificate Errors
189
+
190
+ For self-signed certificates:
191
+ ```python
192
+ "verify_ssl": False
193
+ ```
194
+
195
+ For custom CA certificates, ensure they're in the system trust store.
196
+
197
+ ### Tool Not Found
198
+
199
+ Verify:
200
+ 1. Service name is correct
201
+ 2. Tool name matches exactly
202
+ 3. Tool is included in service configuration
203
+ 4. MCP server is returning tools correctly
204
+
205
+ ### Session Timeouts
206
+
207
+ Increase timeout if needed:
208
+ ```python
209
+ "session_timeout": 600 # 10 minutes
210
+ ```
211
+
212
+ ## Gateway Setup
213
+
214
+ To run the MCP Gateway service:
215
+
216
+ ```bash
217
+ cd mcp_gateway
218
+ python3 gateway_service.py
219
+
220
+ # Or with custom config
221
+ python3 gateway_service.py -c myconfig.json
222
+ ```
223
+
224
+ ## Security Considerations
225
+
226
+ 1. Always use HTTPS in production
227
+ 2. Use strong authentication credentials
228
+ 3. Limit service access to required tools only
229
+ 4. Monitor gateway logs for suspicious activity
230
+ 5. Set appropriate session timeouts
@@ -0,0 +1,10 @@
1
+ """
2
+ Copyright (c) 2025 SignalWire
3
+
4
+ This file is part of the SignalWire AI Agents SDK.
5
+
6
+ Licensed under the MIT License.
7
+ See LICENSE file in the project root for full license information.
8
+ """
9
+
10
+ """MCP Gateway Skill for SignalWire Agents"""