telnyx-mcp-server-fastmcp 0.1.3__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 (40) hide show
  1. telnyx_mcp_server/__init__.py +0 -0
  2. telnyx_mcp_server/__main__.py +23 -0
  3. telnyx_mcp_server/config.py +148 -0
  4. telnyx_mcp_server/mcp.py +148 -0
  5. telnyx_mcp_server/server.py +497 -0
  6. telnyx_mcp_server/telnyx/__init__.py +1 -0
  7. telnyx_mcp_server/telnyx/client.py +363 -0
  8. telnyx_mcp_server/telnyx/services/__init__.py +0 -0
  9. telnyx_mcp_server/telnyx/services/assistants.py +155 -0
  10. telnyx_mcp_server/telnyx/services/call_control.py +217 -0
  11. telnyx_mcp_server/telnyx/services/cloud_storage.py +289 -0
  12. telnyx_mcp_server/telnyx/services/connections.py +92 -0
  13. telnyx_mcp_server/telnyx/services/embeddings.py +52 -0
  14. telnyx_mcp_server/telnyx/services/messaging.py +93 -0
  15. telnyx_mcp_server/telnyx/services/messaging_profiles.py +196 -0
  16. telnyx_mcp_server/telnyx/services/numbers.py +193 -0
  17. telnyx_mcp_server/telnyx/services/secrets.py +74 -0
  18. telnyx_mcp_server/tools/__init__.py +126 -0
  19. telnyx_mcp_server/tools/assistants.py +313 -0
  20. telnyx_mcp_server/tools/call_control.py +242 -0
  21. telnyx_mcp_server/tools/cloud_storage.py +183 -0
  22. telnyx_mcp_server/tools/connections.py +78 -0
  23. telnyx_mcp_server/tools/embeddings.py +80 -0
  24. telnyx_mcp_server/tools/messaging.py +57 -0
  25. telnyx_mcp_server/tools/messaging_profiles.py +123 -0
  26. telnyx_mcp_server/tools/phone_numbers.py +161 -0
  27. telnyx_mcp_server/tools/secrets.py +75 -0
  28. telnyx_mcp_server/tools/sms_conversations.py +455 -0
  29. telnyx_mcp_server/tools/webhooks.py +111 -0
  30. telnyx_mcp_server/utils/__init__.py +0 -0
  31. telnyx_mcp_server/utils/error_handler.py +30 -0
  32. telnyx_mcp_server/utils/logger.py +32 -0
  33. telnyx_mcp_server/utils/service.py +33 -0
  34. telnyx_mcp_server/webhook/__init__.py +25 -0
  35. telnyx_mcp_server/webhook/handler.py +596 -0
  36. telnyx_mcp_server/webhook/server.py +369 -0
  37. telnyx_mcp_server_fastmcp-0.1.3.dist-info/METADATA +430 -0
  38. telnyx_mcp_server_fastmcp-0.1.3.dist-info/RECORD +40 -0
  39. telnyx_mcp_server_fastmcp-0.1.3.dist-info/WHEEL +4 -0
  40. telnyx_mcp_server_fastmcp-0.1.3.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,183 @@
1
+ """Cloud storage related MCP tools."""
2
+
3
+ import os
4
+ from typing import Any, Dict, List
5
+
6
+ from ..mcp import mcp
7
+ from ..telnyx.services.cloud_storage import BucketInfo, CloudStorageService
8
+ from ..utils.error_handler import handle_telnyx_error
9
+ from ..utils.logger import get_logger
10
+
11
+ logger = get_logger(__name__)
12
+
13
+
14
+ def instantiate_cloud_storage() -> CloudStorageService:
15
+ api_key = os.getenv("TELNYX_API_KEY", "")
16
+ if not api_key:
17
+ raise ValueError("TELNYX_API_KEY environment variable must be set")
18
+ return CloudStorageService(
19
+ access_key_id=api_key,
20
+ secret_access_key=api_key,
21
+ )
22
+
23
+
24
+ @mcp.tool()
25
+ async def cloud_storage_create_bucket(request: Dict[str, Any]) -> str:
26
+ """Create a new bucket.
27
+
28
+ Args:
29
+ bucket_name: Required. Name of the bucket to create
30
+ region: Required. Region to create the bucket in (us-east-1, us-west-1, us-central-1)
31
+ Returns:
32
+ str: `Success!!` if it uploaded, otherwise returns an exception message
33
+ """
34
+ try:
35
+ cloud_storage_service = instantiate_cloud_storage()
36
+ if not cloud_storage_service:
37
+ raise RuntimeError(f"Cloud storage service not initialized")
38
+ return cloud_storage_service.create_bucket(
39
+ bucket_name=request["bucket_name"], region=request.get("region")
40
+ )
41
+ except Exception as e:
42
+ logger.error(f"Error creating bucket: {e}")
43
+ raise handle_telnyx_error(e)
44
+
45
+
46
+ @mcp.tool()
47
+ async def cloud_storage_list_buckets() -> List[BucketInfo]:
48
+ """List all buckets across all regions.
49
+
50
+ Returns:
51
+ List[Dict[str, str]]: List of dictionaries containing bucket information:
52
+ - name: Name of the bucket
53
+ - region: Region where the bucket is located
54
+ """
55
+ try:
56
+ cloud_storage_service = instantiate_cloud_storage()
57
+ if not cloud_storage_service:
58
+ raise RuntimeError(f"Cloud storage service not initialized")
59
+ return cloud_storage_service.list_buckets()
60
+ except Exception as e:
61
+ logger.error(f"Error listing buckets: {e}")
62
+ raise handle_telnyx_error(e)
63
+
64
+
65
+ @mcp.tool()
66
+ async def cloud_storage_upload_file(request: Dict[str, Any]) -> str:
67
+ """Upload a file to cloud storage.
68
+
69
+ Args:
70
+ absolute_file_path: Required. Absolute File Path to the file to upload
71
+ object_name: Optional. Name to give the object in storage (defaults to file name)
72
+ bucket_name: Optional. Bucket to upload to (defaults to instance default)
73
+ Returns:
74
+ str: `Success!!` if it uploaded, otherwise returns an exception message
75
+ """
76
+ try:
77
+ cloud_storage_service = instantiate_cloud_storage()
78
+ if not cloud_storage_service:
79
+ raise RuntimeError(f"Cloud storage service not initialized")
80
+ return cloud_storage_service.upload_file(
81
+ file_path=request["absolute_file_path"],
82
+ object_name=request.get("object_name"),
83
+ bucket_name=request.get("bucket_name"),
84
+ )
85
+ except Exception as e:
86
+ logger.error(f"Error uploading file: {e}")
87
+ raise handle_telnyx_error(e)
88
+
89
+
90
+ @mcp.tool()
91
+ async def cloud_storage_download_file(request: Dict[str, Any]) -> str:
92
+ """Download a file from cloud storage.
93
+
94
+ Args:
95
+ object_name: Required. Name of the object to download
96
+ file_path: Required. Path where to save the downloaded file
97
+ bucket_name: Optional. Bucket to download from (defaults to instance default)
98
+ Returns:
99
+ str: 'Success' if the file was downloaded successfully
100
+ """
101
+ try:
102
+ cloud_storage_service = instantiate_cloud_storage()
103
+ if not cloud_storage_service:
104
+ raise RuntimeError(f"Cloud storage service not initialized")
105
+ cloud_storage_service.download_file(
106
+ object_name=request["object_name"],
107
+ file_path=request["file_path"],
108
+ bucket_name=request.get("bucket_name"),
109
+ )
110
+ return "Success"
111
+ except Exception as e:
112
+ logger.error(f"Error downloading file: {e}")
113
+ raise handle_telnyx_error(e)
114
+
115
+
116
+ @mcp.tool()
117
+ async def cloud_storage_list_objects(request: Dict[str, Any]) -> List[str]:
118
+ """List objects in a bucket with optional prefix filtering.
119
+
120
+ Args:
121
+ prefix: Optional. Only list objects beginning with this prefix. Defaults to "".
122
+ bucket_name: Optional. Bucket to list from (defaults to instance default)
123
+
124
+ Returns:
125
+ List[str]: List of object names
126
+ """
127
+ try:
128
+ cloud_storage_service = instantiate_cloud_storage()
129
+ if not cloud_storage_service:
130
+ raise RuntimeError(f"Cloud storage service not initialized")
131
+ return cloud_storage_service.list_objects(
132
+ prefix=request.get("prefix", ""),
133
+ bucket_name=request.get("bucket_name"),
134
+ )
135
+ except Exception as e:
136
+ logger.error(f"Error listing objects: {e}")
137
+ raise handle_telnyx_error(e)
138
+
139
+
140
+ @mcp.tool()
141
+ async def cloud_storage_delete_object(request: Dict[str, Any]) -> str:
142
+ """Delete an object from cloud storage.
143
+
144
+ Args:
145
+ object_name: Required. Name of the object to delete
146
+ bucket_name: Optional. Bucket to delete from (defaults to instance default)
147
+ Returns:
148
+ str: 'Success' if the object was deleted successfully
149
+ """
150
+ try:
151
+ cloud_storage_service = instantiate_cloud_storage()
152
+ if not cloud_storage_service:
153
+ raise RuntimeError(f"Cloud storage service not initialized")
154
+ cloud_storage_service.delete_object(
155
+ object_name=request["object_name"],
156
+ bucket_name=request.get("bucket_name"),
157
+ )
158
+ return "Success"
159
+ except Exception as e:
160
+ logger.error(f"Error deleting object: {e}")
161
+ raise handle_telnyx_error(e)
162
+
163
+
164
+ @mcp.tool()
165
+ async def cloud_storage_get_bucket_location(request: Dict[str, Any]) -> str:
166
+ """Get the region where a bucket is located.
167
+
168
+ Args:
169
+ bucket_name: Optional. Name of the bucket. If None, uses default bucket.
170
+
171
+ Returns:
172
+ str: The region where the bucket is located
173
+ """
174
+ try:
175
+ cloud_storage_service = instantiate_cloud_storage()
176
+ if not cloud_storage_service:
177
+ raise RuntimeError(f"Cloud storage service not initialized")
178
+ return cloud_storage_service.get_bucket_location(
179
+ bucket_name=request.get("bucket_name")
180
+ )
181
+ except Exception as e:
182
+ logger.error(f"Error getting bucket location: {e}")
183
+ raise handle_telnyx_error(e)
@@ -0,0 +1,78 @@
1
+ """Connection related MCP tools."""
2
+
3
+ from typing import Any, Dict
4
+
5
+ from ..mcp import mcp
6
+ from ..telnyx.services.connections import ConnectionsService
7
+ from ..utils.error_handler import handle_telnyx_error
8
+ from ..utils.logger import get_logger
9
+ from ..utils.service import get_authenticated_service
10
+
11
+ logger = get_logger(__name__)
12
+
13
+
14
+ @mcp.tool()
15
+ async def list_connections(request: Dict[str, Any]) -> Dict[str, Any]:
16
+ """List connections.
17
+
18
+ Args:
19
+ page: Optional integer. Page number. Defaults to 1.
20
+ page_size: Optional integer. Page size. Defaults to 20.
21
+ filter_connection_name_contains: Optional. Filter by connection name.
22
+ filter_outbound_voice_profile_id: Optional. Filter by outbound voice profile ID.
23
+ sort: Optional. Sort order (created_at, connection_name, active).
24
+
25
+ Returns:
26
+ Dict[str, Any]: Response data
27
+ """
28
+ try:
29
+ service = get_authenticated_service(ConnectionsService)
30
+ return service.list_connections(request)
31
+ except Exception as e:
32
+ logger.error(f"Error listing connections: {e}")
33
+ raise handle_telnyx_error(e)
34
+
35
+
36
+ @mcp.tool()
37
+ async def get_connection(id: str) -> Dict[str, Any]:
38
+ """Get a connection by ID.
39
+
40
+ Args:
41
+ id: Required. Connection ID.
42
+
43
+ Returns:
44
+ Dict[str, Any]: Response data
45
+ """
46
+ try:
47
+ service = get_authenticated_service(ConnectionsService)
48
+ return service.get_connection(connection_id=id)
49
+ except Exception as e:
50
+ logger.error(f"Error getting connection: {e}")
51
+ raise handle_telnyx_error(e)
52
+
53
+
54
+ @mcp.tool()
55
+ async def update_connection(id: str, data: Dict[str, Any]) -> Dict[str, Any]:
56
+ """Update a connection.
57
+
58
+ Note:
59
+ The Telnyx API does not support updating connections directly.
60
+ Only GET, HEAD, and OPTIONS methods are allowed.
61
+ Please create a new connection with the desired settings instead.
62
+
63
+ Args:
64
+ id: Required. Connection ID.
65
+ data: Required. Update data.
66
+
67
+ Returns:
68
+ Dict[str, Any]: Response data
69
+
70
+ Raises:
71
+ Exception: The Telnyx API does not support updating connections directly.
72
+ """
73
+ try:
74
+ service = get_authenticated_service(ConnectionsService)
75
+ return service.update_connection(connection_id=id, data=data)
76
+ except Exception as e:
77
+ logger.error(f"Error updating connection: {e}")
78
+ raise handle_telnyx_error(e)
@@ -0,0 +1,80 @@
1
+ """Embeddings related MCP tools."""
2
+
3
+ from typing import Any, Dict
4
+
5
+ from ..mcp import mcp
6
+ from ..telnyx.services.embeddings import EmbeddingsService
7
+ from ..utils.error_handler import handle_telnyx_error
8
+ from ..utils.logger import get_logger
9
+ from ..utils.service import get_authenticated_service
10
+
11
+ logger = get_logger(__name__)
12
+
13
+
14
+ @mcp.tool()
15
+ async def list_embedded_buckets() -> Dict[str, Any]:
16
+ """List user embedded buckets.
17
+
18
+ Returns:
19
+ Dict[str, Any]: Response data eg:
20
+ {
21
+ "data": {
22
+ "buckets": [
23
+ "string"
24
+ ]
25
+ }
26
+ }
27
+ """
28
+ try:
29
+ service = get_authenticated_service(EmbeddingsService)
30
+ return service.list_embedded_buckets()
31
+ except Exception as e:
32
+ logger.error(f"Error listing embedded buckets: {e}")
33
+ raise handle_telnyx_error(e)
34
+
35
+
36
+ @mcp.tool()
37
+ async def embed_url(request: Dict[str, Any]) -> Dict[str, Any]:
38
+ """Scrape and embed a given URL. For a given website, this tool will scrape
39
+ the content of the pages and save the content in a new bucket. That bucket will
40
+ be automatically embedded.
41
+
42
+ Args:
43
+ url: Required. URL to be scraped and embedded.
44
+
45
+ Returns:
46
+ Dict[str, Any]: Response data containing bucket information
47
+ """
48
+ try:
49
+ service = get_authenticated_service(EmbeddingsService)
50
+ return service.embed_url(request)
51
+ except Exception as e:
52
+ logger.error(f"Error embedding URL: {e}")
53
+ raise handle_telnyx_error(e)
54
+
55
+
56
+ @mcp.tool()
57
+ async def create_embeddings(request: Dict[str, Any]) -> Dict[str, Any]:
58
+ """Embed a bucket that containe files.
59
+
60
+ Args:
61
+ bucket_name: Required. Bucket Name. The bucket must exist (string)
62
+ document_chunk_size: Optional. Document Chunk Size (integer)
63
+ document_chunk_overlap_size: Optional. Document Chunk Overlap Size (integer)
64
+ embedding_model: Optional. Supported models (thenlper/gte-large,
65
+ intfloat/multilingual-e5-large, sentence-transformers/all-mpnet-base-v2)
66
+ to vectorize and embed documents.
67
+ loader: Optional. (default, intercom) (string)
68
+
69
+ Agent should prefer only rely on required fields unless user explicitly
70
+ provides values for optional fields.
71
+
72
+ Returns:
73
+ Dict[str, Any]: Response data containing the embeddings
74
+ """
75
+ try:
76
+ service = get_authenticated_service(EmbeddingsService)
77
+ return service.create_embeddings(request)
78
+ except Exception as e:
79
+ logger.error(f"Error creating embeddings: {e}")
80
+ raise handle_telnyx_error(e)
@@ -0,0 +1,57 @@
1
+ """Messaging related MCP tools."""
2
+
3
+ from typing import Any, Dict
4
+
5
+ from ..mcp import mcp
6
+ from ..telnyx.services.messaging import MessagingService
7
+ from ..utils.error_handler import handle_telnyx_error
8
+ from ..utils.logger import get_logger
9
+ from ..utils.service import get_authenticated_service
10
+
11
+ logger = get_logger(__name__)
12
+
13
+
14
+ @mcp.tool()
15
+ async def send_message(request: Dict[str, Any]) -> Dict[str, Any]:
16
+ """Send a message.
17
+
18
+ Args:
19
+ from_: Required. Sending address (phone number, alphanumeric sender ID, or short code).
20
+ to: Required. Receiving address(es).
21
+ text: Required. Message text.
22
+ messaging_profile_id: Optional. Messaging profile ID.
23
+ subject: Optional. Message subject.
24
+ media_urls: Optional. List of media URLs.
25
+ webhook_url: Optional. Webhook URL.
26
+ webhook_failover_url: Optional. Webhook failover URL.
27
+ use_profile_webhooks: Optional boolean. Whether to use profile webhooks. Defaults to True.
28
+ type: Optional. The protocol for sending the message, either "SMS" or "MMS".
29
+ auto_detect: Optional boolean. Automatically detect if an SMS message is unusually long.
30
+
31
+ Returns:
32
+ Dict[str, Any]: Response data
33
+ """
34
+ try:
35
+ service = get_authenticated_service(MessagingService)
36
+ return service.send_message(**request)
37
+ except Exception as e:
38
+ logger.error(f"Error sending message: {e}")
39
+ raise handle_telnyx_error(e)
40
+
41
+
42
+ @mcp.tool()
43
+ async def get_message(message_id: str) -> Dict[str, Any]:
44
+ """Retrieve a message by ID.
45
+
46
+ Args:
47
+ message_id: The ID of the message to retrieve
48
+
49
+ Returns:
50
+ Dict[str, Any]: Response data containing message details
51
+ """
52
+ try:
53
+ service = get_authenticated_service(MessagingService)
54
+ return service.get_message(message_id)
55
+ except Exception as e:
56
+ logger.error(f"Error retrieving message: {e}")
57
+ raise handle_telnyx_error(e)
@@ -0,0 +1,123 @@
1
+ """Messaging profiles related MCP tools."""
2
+
3
+ from typing import Any, Dict
4
+
5
+ from ..mcp import mcp
6
+ from ..telnyx.services.messaging_profiles import MessagingProfilesService
7
+ from ..utils.error_handler import handle_telnyx_error
8
+ from ..utils.logger import get_logger
9
+ from ..utils.service import get_authenticated_service
10
+
11
+ logger = get_logger(__name__)
12
+
13
+
14
+ @mcp.tool()
15
+ async def list_messaging_profiles(request: Dict[str, Any]) -> Dict[str, Any]:
16
+ """List messaging profiles.
17
+
18
+ Args:
19
+ page: Optional integer. Page number. Defaults to 1.
20
+ page_size: Optional integer. Page size. Defaults to 20.
21
+ filter_name: Optional. Filter by profile name.
22
+
23
+ Returns:
24
+ Dict[str, Any]: Response data
25
+ """
26
+ try:
27
+ service = get_authenticated_service(MessagingProfilesService)
28
+ return service.list_messaging_profiles(**request)
29
+ except Exception as e:
30
+ logger.error(f"Error listing messaging profiles: {e}")
31
+ raise handle_telnyx_error(e)
32
+
33
+
34
+ @mcp.tool()
35
+ async def create_messaging_profile(request: Dict[str, Any]) -> Dict[str, Any]:
36
+ """Create a messaging profile.
37
+
38
+ Args:
39
+ name: Required. A user friendly name for the messaging profile.
40
+ whitelisted_destinations: Required. List of destinations to which messages are allowed to be sent (ISO 3166-1 alpha-2 country codes). Use ["*"] to allow all destinations.
41
+ enabled: Optional boolean. Specifies whether the messaging profile is enabled. Defaults to True.
42
+ webhook_url: Optional. The URL where webhooks related to this messaging profile will be sent.
43
+ webhook_failover_url: Optional. The failover URL for webhooks if the primary URL fails.
44
+ webhook_api_version: Optional. Webhook format version ("1", "2", or "2010-04-01"). Defaults to "2".
45
+ number_pool_settings: Optional dictionary. Number pool configuration with possible settings:
46
+ - use_pool: Boolean indicating whether to use number pool.
47
+ - sticky_sender: Boolean indicating whether to use sticky sender.
48
+ - pool_weights: Dictionary mapping phone number types to weights.
49
+ url_shortener_settings: Optional dictionary. URL shortener configuration with possible settings:
50
+ - enabled: Boolean indicating whether URL shortening is enabled.
51
+ - domains: List of domains to be shortened.
52
+ alpha_sender: Optional. The alphanumeric sender ID for destinations requiring it.
53
+ daily_spend_limit: Optional. Maximum daily spend in USD before midnight UTC.
54
+ daily_spend_limit_enabled: Optional boolean. Whether to enforce the daily spend limit.
55
+ mms_fall_back_to_sms: Optional boolean. Enables SMS fallback for MMS messages.
56
+ mms_transcoding: Optional boolean. Enables automated resizing of MMS media.
57
+
58
+ Returns:
59
+ Dict[str, Any]: Response data
60
+ """
61
+ try:
62
+ service = get_authenticated_service(MessagingProfilesService)
63
+ return service.create_messaging_profile(**request)
64
+ except Exception as e:
65
+ logger.error(f"Error creating messaging profile: {e}")
66
+ raise handle_telnyx_error(e)
67
+
68
+
69
+ @mcp.tool()
70
+ async def get_messaging_profile(profile_id: str) -> Dict[str, Any]:
71
+ """Retrieve a messaging profile by ID.
72
+
73
+ Args:
74
+ profile_id: The ID of the messaging profile to retrieve
75
+
76
+ Returns:
77
+ Dict[str, Any]: Response data containing messaging profile details
78
+ """
79
+ try:
80
+ service = get_authenticated_service(MessagingProfilesService)
81
+ return service.get_messaging_profile(profile_id)
82
+ except Exception as e:
83
+ logger.error(f"Error retrieving messaging profile: {e}")
84
+ raise handle_telnyx_error(e)
85
+
86
+
87
+ @mcp.tool()
88
+ async def update_messaging_profile(
89
+ profile_id: str, request: Dict[str, Any]
90
+ ) -> Dict[str, Any]:
91
+ """Update a messaging profile.
92
+
93
+ Args:
94
+ profile_id: Required. The ID of the messaging profile to update.
95
+ name: Optional. A user friendly name for the messaging profile.
96
+ enabled: Optional boolean. Specifies whether the messaging profile is enabled.
97
+ webhook_url: Optional. The URL where webhooks related to this messaging profile will be sent.
98
+ webhook_failover_url: Optional. The failover URL for webhooks if the primary URL fails.
99
+ webhook_api_version: Optional. Webhook format version ("1", "2", or "2010-04-01").
100
+ whitelisted_destinations: Optional list. Destinations to which messages are allowed (ISO 3166-1 alpha-2 country codes). Use ["*"] to allow all destinations.
101
+ v1_secret: Optional. Secret used to authenticate with v1 endpoints.
102
+ number_pool_settings: Optional dictionary. Number pool configuration with possible settings:
103
+ - use_pool: Boolean indicating whether to use number pool.
104
+ - sticky_sender: Boolean indicating whether to use sticky sender.
105
+ - pool_weights: Dictionary mapping phone number types to weights.
106
+ url_shortener_settings: Optional dictionary. URL shortener configuration with possible settings:
107
+ - enabled: Boolean indicating whether URL shortening is enabled.
108
+ - domains: List of domains to be shortened.
109
+ alpha_sender: Optional. The alphanumeric sender ID for destinations requiring it.
110
+ daily_spend_limit: Optional. Maximum daily spend in USD before midnight UTC.
111
+ daily_spend_limit_enabled: Optional boolean. Whether to enforce the daily spend limit.
112
+ mms_fall_back_to_sms: Optional boolean. Enables SMS fallback for MMS messages.
113
+ mms_transcoding: Optional boolean. Enables automated resizing of MMS media.
114
+
115
+ Returns:
116
+ Dict[str, Any]: Response data
117
+ """
118
+ try:
119
+ service = get_authenticated_service(MessagingProfilesService)
120
+ return service.update_messaging_profile(profile_id, **request)
121
+ except Exception as e:
122
+ logger.error(f"Error updating messaging profile: {e}")
123
+ raise handle_telnyx_error(e)
@@ -0,0 +1,161 @@
1
+ """Phone number related MCP tools."""
2
+
3
+ from typing import Any, Dict
4
+
5
+ from pydantic import Field
6
+
7
+ from ..mcp import mcp
8
+ from ..telnyx.services.numbers import NumbersService
9
+ from ..utils.error_handler import handle_telnyx_error
10
+ from ..utils.logger import get_logger
11
+ from ..utils.service import get_authenticated_service
12
+
13
+ logger = get_logger(__name__)
14
+
15
+
16
+ @mcp.tool()
17
+ async def list_phone_numbers(request: Dict[str, Any]) -> Dict[str, Any]:
18
+ """List phone numbers.
19
+
20
+ Args:
21
+ page: Optional integer. Page number. Defaults to 1.
22
+ page_size: Optional integer. Page size. Defaults to 20.
23
+ filter_tag: Optional. Filter by phone number tag.
24
+ filter_phone_number: Optional. Filter by phone number.
25
+ filter_status: Optional. Filter by phone number status.
26
+ filter_country_iso_alpha2: Optional. Filter by country ISO alpha-2 code.
27
+
28
+ Returns:
29
+ Dict[str, Any]: Response data
30
+ """
31
+ try:
32
+ service = get_authenticated_service(NumbersService)
33
+ return service.list_phone_numbers(**request)
34
+ except Exception as e:
35
+ logger.error(f"Error listing phone numbers: {e}")
36
+ raise handle_telnyx_error(e)
37
+
38
+
39
+ @mcp.tool()
40
+ async def get_phone_number(
41
+ id: str = Field(..., description="Phone number ID as string"),
42
+ ) -> Dict[str, Any]:
43
+ """Get a phone number by ID.
44
+
45
+ Args:
46
+ id: Phone number ID as string
47
+
48
+ Returns:
49
+ Dict[str, Any]: Response data containing Number Object(s) (record_type: "phone_number")
50
+ """
51
+ try:
52
+ service = get_authenticated_service(NumbersService)
53
+ return service.get_phone_number(id=id)
54
+ except Exception as e:
55
+ logger.error(f"Error getting phone number: {e}")
56
+ raise handle_telnyx_error(e)
57
+
58
+
59
+ @mcp.tool()
60
+ async def update_phone_number(
61
+ id: str, request: Dict[str, Any]
62
+ ) -> Dict[str, Any]:
63
+ """Update a phone number.
64
+
65
+ Args:
66
+ id: Required. Phone number ID.
67
+ connection_id: Optional. Connection ID to associate with the number.
68
+ tags: Optional. List of tags to associate with the number.
69
+
70
+ Returns:
71
+ Dict[str, Any]: Response data
72
+ """
73
+ try:
74
+ service = get_authenticated_service(NumbersService)
75
+ return service.update_phone_number(id=id, data=request)
76
+ except Exception as e:
77
+ logger.error(f"Error updating phone number: {e}")
78
+ raise handle_telnyx_error(e)
79
+
80
+
81
+ @mcp.tool()
82
+ async def list_available_phone_numbers(
83
+ request: Dict[str, Any],
84
+ ) -> Dict[str, Any]:
85
+ """List available phone numbers.
86
+
87
+ Args:
88
+ page: Optional integer. Page number. Defaults to 1.
89
+ page_size: Optional integer. Page size. Defaults to 20.
90
+ filter_phone_number_starts_with: Optional. Filter numbers starting with pattern.
91
+ filter_phone_number_ends_with: Optional. Filter numbers ending with pattern.
92
+ filter_phone_number_contains: Optional. Filter numbers containing pattern.
93
+ filter_locality: Optional. Filter by locality (city).
94
+ filter_administrative_area: Optional. Filter by administrative area (state).
95
+ filter_country_code: Optional. Filter by country code.
96
+ filter_features: Optional. List of features to filter by.
97
+
98
+ Returns:
99
+ Dict[str, Any]: Response data
100
+ """
101
+ try:
102
+ service = get_authenticated_service(NumbersService)
103
+ filter_params = {
104
+ key: value
105
+ for key, value in request.items()
106
+ if key.startswith("filter_")
107
+ }
108
+ base_params = {
109
+ key: value
110
+ for key, value in request.items()
111
+ if not key.startswith("filter_")
112
+ }
113
+ return service.list_available_phone_numbers(
114
+ **base_params, **filter_params
115
+ )
116
+ except Exception as e:
117
+ logger.error(f"Error listing available phone numbers: {e}")
118
+ raise handle_telnyx_error(e)
119
+
120
+
121
+ @mcp.tool()
122
+ async def initiate_phone_number_order(
123
+ request: Dict[str, Any],
124
+ ) -> Dict[str, Any]:
125
+ """Initiate a phone number order.
126
+
127
+ Args:
128
+ phone_number: Required. Phone number to buy.
129
+ connection_id: Optional. Connection ID to associate with the number.
130
+
131
+ Returns:
132
+ Dict[str, Any]: Response data
133
+ """
134
+ try:
135
+ service = get_authenticated_service(NumbersService)
136
+ return service.buy_phone_number(**request)
137
+ except Exception as e:
138
+ logger.error(f"Error buying phone number: {e}")
139
+ raise handle_telnyx_error(e)
140
+
141
+
142
+ @mcp.tool()
143
+ async def update_phone_number_messaging_settings(
144
+ id: str, request: Dict[str, Any]
145
+ ) -> Dict[str, Any]:
146
+ """Update the messaging profile and/or messaging product of a phone number.
147
+
148
+ Args:
149
+ id: Required. The phone number ID to update.
150
+ messaging_profile_id: Optional. Configure the messaging profile this phone number is assigned to. Set to null to keep the current value, set to empty string to unassign, or set to a UUID to assign to that messaging profile.
151
+ messaging_product: Optional. Configure the messaging product for this number. Set to null to keep the current value, or set to a product ID to change.
152
+
153
+ Returns:
154
+ Dict[str, Any]: Response data
155
+ """
156
+ try:
157
+ service = get_authenticated_service(NumbersService)
158
+ return service.update_phone_number_messaging_settings(id=id, **request)
159
+ except Exception as e:
160
+ logger.error(f"Error updating phone number messaging settings: {e}")
161
+ raise handle_telnyx_error(e)