voipbin-mcp 0.1.0__tar.gz

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 (34) hide show
  1. voipbin_mcp-0.1.0/.github/workflows/ci.yml +20 -0
  2. voipbin_mcp-0.1.0/.github/workflows/publish.yml +16 -0
  3. voipbin_mcp-0.1.0/.gitignore +15 -0
  4. voipbin_mcp-0.1.0/LICENSE +21 -0
  5. voipbin_mcp-0.1.0/PKG-INFO +159 -0
  6. voipbin_mcp-0.1.0/README.md +130 -0
  7. voipbin_mcp-0.1.0/pyproject.toml +52 -0
  8. voipbin_mcp-0.1.0/src/voipbin_mcp/__init__.py +1 -0
  9. voipbin_mcp-0.1.0/src/voipbin_mcp/client.py +106 -0
  10. voipbin_mcp-0.1.0/src/voipbin_mcp/server.py +47 -0
  11. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/__init__.py +20 -0
  12. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/activeflows.py +45 -0
  13. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/agents.py +33 -0
  14. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/ais.py +72 -0
  15. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/billings.py +31 -0
  16. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/calls.py +77 -0
  17. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/campaigns.py +91 -0
  18. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/conferences.py +76 -0
  19. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/contacts.py +109 -0
  20. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/conversations.py +33 -0
  21. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/customer.py +14 -0
  22. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/emails.py +53 -0
  23. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/extensions.py +33 -0
  24. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/flows.py +93 -0
  25. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/messages.py +53 -0
  26. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/numbers.py +31 -0
  27. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/queues.py +33 -0
  28. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/routes.py +33 -0
  29. voipbin_mcp-0.1.0/src/voipbin_mcp/tools/tags.py +33 -0
  30. voipbin_mcp-0.1.0/tests/test_client.py +116 -0
  31. voipbin_mcp-0.1.0/tests/test_server.py +52 -0
  32. voipbin_mcp-0.1.0/tests/test_tools_calls.py +130 -0
  33. voipbin_mcp-0.1.0/tests/test_tools_flows.py +163 -0
  34. voipbin_mcp-0.1.0/uv.lock +905 -0
@@ -0,0 +1,20 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.10", "3.11", "3.12"]
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ - uses: astral-sh/setup-uv@v4
18
+ - run: uv venv --python ${{ matrix.python-version }}
19
+ - run: uv pip install -e ".[dev]"
20
+ - run: uv run pytest tests/ -v
@@ -0,0 +1,16 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ id-token: write
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: astral-sh/setup-uv@v4
15
+ - run: uv build
16
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,15 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .venv/
7
+ .env
8
+ CLAUDE.md
9
+ *.pem
10
+ *.key
11
+ *.p12
12
+ id_rsa
13
+ .DS_Store
14
+ .idea/
15
+ .vscode/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 VoIPbin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,159 @@
1
+ Metadata-Version: 2.4
2
+ Name: voipbin-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server for the VoIPbin CPaaS platform
5
+ Project-URL: Homepage, https://voipbin.net
6
+ Project-URL: Repository, https://github.com/voipbin/mcp
7
+ Project-URL: Bug Tracker, https://github.com/voipbin/mcp/issues
8
+ Author-email: VoIPbin <support@voipbin.net>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: ai,cpaas,mcp,model-context-protocol,telephony,voip,voipbin
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Communications :: Telephony
20
+ Classifier: Topic :: Software Development :: Libraries
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: httpx>=0.27.0
23
+ Requires-Dist: mcp>=1.0.0
24
+ Provides-Extra: dev
25
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
26
+ Requires-Dist: pytest>=8.0; extra == 'dev'
27
+ Requires-Dist: respx>=0.21; extra == 'dev'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # VoIPbin MCP Server
31
+
32
+ An MCP (Model Context Protocol) server that enables AI assistants to interact with the VoIPbin CPaaS platform. It exposes VoIPbin's communication APIs -- calls, flows, messaging, conferencing, AI, and more -- as tools that any MCP-compatible client can use to manage and automate cloud communications.
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ pip install voipbin-mcp
38
+ ```
39
+
40
+ Or run directly without installing:
41
+
42
+ ```bash
43
+ uvx voipbin-mcp
44
+ ```
45
+
46
+ ## Configuration
47
+
48
+ ### Claude Code
49
+
50
+ Add to `~/.claude.json`:
51
+
52
+ ```json
53
+ {
54
+ "mcpServers": {
55
+ "voipbin": {
56
+ "command": "uvx",
57
+ "args": ["voipbin-mcp"],
58
+ "env": {
59
+ "VOIPBIN_API_KEY": "your-access-key"
60
+ }
61
+ }
62
+ }
63
+ }
64
+ ```
65
+
66
+ ### Cursor
67
+
68
+ Add to `.cursor/mcp.json` in your project directory:
69
+
70
+ ```json
71
+ {
72
+ "mcpServers": {
73
+ "voipbin": {
74
+ "command": "uvx",
75
+ "args": ["voipbin-mcp"],
76
+ "env": {
77
+ "VOIPBIN_API_KEY": "your-access-key"
78
+ }
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ ### Generic MCP Client
85
+
86
+ Any MCP-compatible client can connect by running the `voipbin-mcp` command with the `VOIPBIN_API_KEY` environment variable set:
87
+
88
+ ```bash
89
+ VOIPBIN_API_KEY=your-access-key voipbin-mcp
90
+ ```
91
+
92
+ ## Available Tools
93
+
94
+ | Resource | Tools |
95
+ |---|---|
96
+ | Calls | `list_calls`, `get_call`, `create_call`, `hangup_call` |
97
+ | Flows | `list_flows`, `get_flow`, `create_flow`, `update_flow`, `delete_flow` |
98
+ | Active Flows | `list_activeflows`, `get_activeflow`, `stop_activeflow` |
99
+ | Agents | `list_agents`, `get_agent` |
100
+ | Numbers | `list_numbers`, `get_number` |
101
+ | Contacts | `list_contacts`, `get_contact`, `create_contact`, `update_contact`, `delete_contact` |
102
+ | Messages | `list_messages`, `get_message`, `send_message` |
103
+ | Emails | `list_emails`, `get_email`, `send_email` |
104
+ | Conversations | `list_conversations`, `get_conversation` |
105
+ | Conferences | `list_conferences`, `get_conference`, `create_conference`, `delete_conference` |
106
+ | Campaigns | `list_campaigns`, `get_campaign`, `create_campaign`, `update_campaign`, `delete_campaign` |
107
+ | Queues | `list_queues`, `get_queue` |
108
+ | Routes | `list_routes`, `get_route` |
109
+ | Billings | `list_billings`, `get_billing` |
110
+ | AIs | `list_ais`, `get_ai`, `create_ai` |
111
+ | Customer | `get_customer` |
112
+ | Tags | `list_tags`, `get_tag` |
113
+ | Extensions | `list_extensions`, `get_extension` |
114
+
115
+ ## Example Usage
116
+
117
+ Once configured, you can ask your AI assistant to interact with VoIPbin directly:
118
+
119
+ **List active calls:**
120
+ > "Show me all my active calls"
121
+
122
+ The AI uses `list_calls` to fetch and display your current calls.
123
+
124
+ **Create a flow:**
125
+ > "Create a flow that answers and plays a greeting"
126
+
127
+ The AI uses `create_flow` to build a call flow with answer and play actions.
128
+
129
+ **Check billing:**
130
+ > "What are my recent billing charges?"
131
+
132
+ The AI uses `list_billings` to retrieve your billing history.
133
+
134
+ **Manage contacts:**
135
+ > "Add a new contact named John with phone number +1234567890"
136
+
137
+ The AI uses `create_contact` to create the contact in your account.
138
+
139
+ ## Security Note
140
+
141
+ Your VoIPbin API key is sent as a URL query parameter (`accesskey=`) on every request. The connection uses HTTPS, so the key is encrypted in transit. However, be aware that URL parameters may be recorded in server access logs and proxy logs. Avoid sharing unredacted debug output, and rotate your key if you suspect it has been exposed.
142
+
143
+ ## Getting an API Key
144
+
145
+ Sign up at [voipbin.net](https://voipbin.net) and create an access key through the API or the admin console at [admin.voipbin.net](https://admin.voipbin.net).
146
+
147
+ ## Development
148
+
149
+ ```bash
150
+ git clone https://github.com/voipbin/mcp.git
151
+ cd mcp
152
+ uv venv
153
+ uv pip install -e ".[dev]"
154
+ uv run pytest tests/ -v
155
+ ```
156
+
157
+ ## License
158
+
159
+ MIT
@@ -0,0 +1,130 @@
1
+ # VoIPbin MCP Server
2
+
3
+ An MCP (Model Context Protocol) server that enables AI assistants to interact with the VoIPbin CPaaS platform. It exposes VoIPbin's communication APIs -- calls, flows, messaging, conferencing, AI, and more -- as tools that any MCP-compatible client can use to manage and automate cloud communications.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install voipbin-mcp
9
+ ```
10
+
11
+ Or run directly without installing:
12
+
13
+ ```bash
14
+ uvx voipbin-mcp
15
+ ```
16
+
17
+ ## Configuration
18
+
19
+ ### Claude Code
20
+
21
+ Add to `~/.claude.json`:
22
+
23
+ ```json
24
+ {
25
+ "mcpServers": {
26
+ "voipbin": {
27
+ "command": "uvx",
28
+ "args": ["voipbin-mcp"],
29
+ "env": {
30
+ "VOIPBIN_API_KEY": "your-access-key"
31
+ }
32
+ }
33
+ }
34
+ }
35
+ ```
36
+
37
+ ### Cursor
38
+
39
+ Add to `.cursor/mcp.json` in your project directory:
40
+
41
+ ```json
42
+ {
43
+ "mcpServers": {
44
+ "voipbin": {
45
+ "command": "uvx",
46
+ "args": ["voipbin-mcp"],
47
+ "env": {
48
+ "VOIPBIN_API_KEY": "your-access-key"
49
+ }
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ ### Generic MCP Client
56
+
57
+ Any MCP-compatible client can connect by running the `voipbin-mcp` command with the `VOIPBIN_API_KEY` environment variable set:
58
+
59
+ ```bash
60
+ VOIPBIN_API_KEY=your-access-key voipbin-mcp
61
+ ```
62
+
63
+ ## Available Tools
64
+
65
+ | Resource | Tools |
66
+ |---|---|
67
+ | Calls | `list_calls`, `get_call`, `create_call`, `hangup_call` |
68
+ | Flows | `list_flows`, `get_flow`, `create_flow`, `update_flow`, `delete_flow` |
69
+ | Active Flows | `list_activeflows`, `get_activeflow`, `stop_activeflow` |
70
+ | Agents | `list_agents`, `get_agent` |
71
+ | Numbers | `list_numbers`, `get_number` |
72
+ | Contacts | `list_contacts`, `get_contact`, `create_contact`, `update_contact`, `delete_contact` |
73
+ | Messages | `list_messages`, `get_message`, `send_message` |
74
+ | Emails | `list_emails`, `get_email`, `send_email` |
75
+ | Conversations | `list_conversations`, `get_conversation` |
76
+ | Conferences | `list_conferences`, `get_conference`, `create_conference`, `delete_conference` |
77
+ | Campaigns | `list_campaigns`, `get_campaign`, `create_campaign`, `update_campaign`, `delete_campaign` |
78
+ | Queues | `list_queues`, `get_queue` |
79
+ | Routes | `list_routes`, `get_route` |
80
+ | Billings | `list_billings`, `get_billing` |
81
+ | AIs | `list_ais`, `get_ai`, `create_ai` |
82
+ | Customer | `get_customer` |
83
+ | Tags | `list_tags`, `get_tag` |
84
+ | Extensions | `list_extensions`, `get_extension` |
85
+
86
+ ## Example Usage
87
+
88
+ Once configured, you can ask your AI assistant to interact with VoIPbin directly:
89
+
90
+ **List active calls:**
91
+ > "Show me all my active calls"
92
+
93
+ The AI uses `list_calls` to fetch and display your current calls.
94
+
95
+ **Create a flow:**
96
+ > "Create a flow that answers and plays a greeting"
97
+
98
+ The AI uses `create_flow` to build a call flow with answer and play actions.
99
+
100
+ **Check billing:**
101
+ > "What are my recent billing charges?"
102
+
103
+ The AI uses `list_billings` to retrieve your billing history.
104
+
105
+ **Manage contacts:**
106
+ > "Add a new contact named John with phone number +1234567890"
107
+
108
+ The AI uses `create_contact` to create the contact in your account.
109
+
110
+ ## Security Note
111
+
112
+ Your VoIPbin API key is sent as a URL query parameter (`accesskey=`) on every request. The connection uses HTTPS, so the key is encrypted in transit. However, be aware that URL parameters may be recorded in server access logs and proxy logs. Avoid sharing unredacted debug output, and rotate your key if you suspect it has been exposed.
113
+
114
+ ## Getting an API Key
115
+
116
+ Sign up at [voipbin.net](https://voipbin.net) and create an access key through the API or the admin console at [admin.voipbin.net](https://admin.voipbin.net).
117
+
118
+ ## Development
119
+
120
+ ```bash
121
+ git clone https://github.com/voipbin/mcp.git
122
+ cd mcp
123
+ uv venv
124
+ uv pip install -e ".[dev]"
125
+ uv run pytest tests/ -v
126
+ ```
127
+
128
+ ## License
129
+
130
+ MIT
@@ -0,0 +1,52 @@
1
+ [project]
2
+ name = "voipbin-mcp"
3
+ version = "0.1.0"
4
+ description = "MCP server for the VoIPbin CPaaS platform"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ requires-python = ">=3.10"
8
+ authors = [
9
+ {name = "VoIPbin", email = "support@voipbin.net"},
10
+ ]
11
+ keywords = ["mcp", "voipbin", "cpaas", "voip", "telephony", "ai", "model-context-protocol"]
12
+ classifiers = [
13
+ "Development Status :: 4 - Beta",
14
+ "Intended Audience :: Developers",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.10",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ "Topic :: Communications :: Telephony",
21
+ "Topic :: Software Development :: Libraries",
22
+ ]
23
+ dependencies = [
24
+ "mcp>=1.0.0",
25
+ "httpx>=0.27.0",
26
+ ]
27
+
28
+ [project.urls]
29
+ Homepage = "https://voipbin.net"
30
+ Repository = "https://github.com/voipbin/mcp"
31
+ "Bug Tracker" = "https://github.com/voipbin/mcp/issues"
32
+
33
+ [project.scripts]
34
+ voipbin-mcp = "voipbin_mcp.server:main"
35
+
36
+ [build-system]
37
+ requires = ["hatchling"]
38
+ build-backend = "hatchling.build"
39
+
40
+ [tool.hatch.build.targets.wheel]
41
+ packages = ["src/voipbin_mcp"]
42
+
43
+ [tool.pytest.ini_options]
44
+ asyncio_mode = "auto"
45
+ testpaths = ["tests"]
46
+
47
+ [project.optional-dependencies]
48
+ dev = [
49
+ "pytest>=8.0",
50
+ "pytest-asyncio>=0.23",
51
+ "respx>=0.21",
52
+ ]
@@ -0,0 +1 @@
1
+ """VoIPbin MCP Server - MCP tools for the VoIPbin CPaaS platform."""
@@ -0,0 +1,106 @@
1
+ """HTTP client for the VoIPbin REST API."""
2
+
3
+ import json
4
+ import os
5
+ from typing import Any
6
+
7
+ import httpx
8
+
9
+ BASE_URL = "https://api.voipbin.net/v1.0"
10
+
11
+
12
+ class VoIPbinAPIError(Exception):
13
+ """Raised when a VoIPbin API call fails."""
14
+
15
+ def __init__(self, status_code: int, message: str):
16
+ self.status_code = status_code
17
+ self.message = message
18
+ super().__init__(message)
19
+
20
+
21
+ class VoIPbinClient:
22
+ """Async HTTP client for the VoIPbin REST API."""
23
+
24
+ def __init__(self):
25
+ self.api_key = os.environ.get("VOIPBIN_API_KEY")
26
+ if not self.api_key:
27
+ raise ValueError(
28
+ "VOIPBIN_API_KEY environment variable is required. "
29
+ "Set it to your VoIPbin access key."
30
+ )
31
+ self.base_url = BASE_URL
32
+ self._client = httpx.AsyncClient(timeout=30.0)
33
+
34
+ def __repr__(self) -> str:
35
+ base_url = getattr(self, "base_url", "<not initialised>")
36
+ return f"VoIPbinClient(base_url={base_url!r})"
37
+
38
+ def _params_with_auth(self, params: dict[str, Any] | None = None) -> dict[str, Any]:
39
+ """Add accesskey to query parameters."""
40
+ result = dict(params) if params else {}
41
+ result["accesskey"] = self.api_key
42
+ return result
43
+
44
+ def _handle_error(self, response: httpx.Response) -> None:
45
+ """Raise descriptive errors for non-2xx responses."""
46
+ if response.is_success:
47
+ return
48
+
49
+ try:
50
+ body = response.json()
51
+ detail = body.get("message", "")
52
+ except Exception:
53
+ detail = response.text
54
+
55
+ error_map = {
56
+ 401: "Invalid or expired API key",
57
+ 402: "Insufficient credits",
58
+ 403: "Permission denied",
59
+ 404: f"Resource not found: {detail}",
60
+ 409: f"Conflict: {detail}",
61
+ }
62
+
63
+ message = error_map.get(response.status_code, f"API error {response.status_code}: {detail}")
64
+ raise VoIPbinAPIError(response.status_code, message)
65
+
66
+ async def get(self, path: str, params: dict[str, Any] | None = None) -> dict:
67
+ """Send a GET request."""
68
+ response = await self._client.get(
69
+ f"{self.base_url}{path}",
70
+ params=self._params_with_auth(params),
71
+ )
72
+ self._handle_error(response)
73
+ return response.json()
74
+
75
+ async def post(self, path: str, json: dict[str, Any] | None = None) -> dict:
76
+ """Send a POST request."""
77
+ response = await self._client.post(
78
+ f"{self.base_url}{path}",
79
+ params=self._params_with_auth(),
80
+ json=json,
81
+ )
82
+ self._handle_error(response)
83
+ return response.json()
84
+
85
+ async def put(self, path: str, json: dict[str, Any] | None = None) -> dict:
86
+ """Send a PUT request."""
87
+ response = await self._client.put(
88
+ f"{self.base_url}{path}",
89
+ params=self._params_with_auth(),
90
+ json=json,
91
+ )
92
+ self._handle_error(response)
93
+ return response.json()
94
+
95
+ async def delete(self, path: str) -> dict:
96
+ """Send a DELETE request."""
97
+ response = await self._client.delete(
98
+ f"{self.base_url}{path}",
99
+ params=self._params_with_auth(),
100
+ )
101
+ self._handle_error(response)
102
+ return response.json()
103
+
104
+ async def close(self):
105
+ """Close the underlying HTTP client."""
106
+ await self._client.aclose()
@@ -0,0 +1,47 @@
1
+ """VoIPbin MCP server entry point."""
2
+
3
+ import json
4
+
5
+ from mcp.server.fastmcp import FastMCP
6
+
7
+ from voipbin_mcp.client import VoIPbinClient
8
+
9
+ mcp = FastMCP("voipbin")
10
+
11
+ # Lazy-initialized client (created on first tool call)
12
+ _client: VoIPbinClient | None = None
13
+
14
+
15
+ def get_client() -> VoIPbinClient:
16
+ """Get or create the VoIPbin HTTP client."""
17
+ global _client
18
+ if _client is None:
19
+ _client = VoIPbinClient()
20
+ return _client
21
+
22
+
23
+ def format_response(data: dict) -> str:
24
+ """Format API response as readable JSON string."""
25
+ return json.dumps(data, indent=2, default=str)
26
+
27
+
28
+ def validate_page_size(page_size: int) -> int:
29
+ """Clamp page_size to a safe integer range (1–100)."""
30
+ try:
31
+ page_size = int(page_size)
32
+ except (TypeError, ValueError):
33
+ page_size = 10
34
+ return max(1, min(page_size, 100))
35
+
36
+
37
+ # Import tools to register them on the mcp instance
38
+ import voipbin_mcp.tools # noqa: E402, F401
39
+
40
+
41
+ def main():
42
+ """Run the VoIPbin MCP server over stdio."""
43
+ mcp.run(transport="stdio")
44
+
45
+
46
+ if __name__ == "__main__":
47
+ main()
@@ -0,0 +1,20 @@
1
+ """VoIPbin MCP tools — importing registers them on the server."""
2
+
3
+ from voipbin_mcp.tools import calls # noqa: F401
4
+ from voipbin_mcp.tools import flows # noqa: F401
5
+ from voipbin_mcp.tools import activeflows # noqa: F401
6
+ from voipbin_mcp.tools import agents # noqa: F401
7
+ from voipbin_mcp.tools import numbers # noqa: F401
8
+ from voipbin_mcp.tools import contacts # noqa: F401
9
+ from voipbin_mcp.tools import messages # noqa: F401
10
+ from voipbin_mcp.tools import emails # noqa: F401
11
+ from voipbin_mcp.tools import conversations # noqa: F401
12
+ from voipbin_mcp.tools import conferences # noqa: F401
13
+ from voipbin_mcp.tools import campaigns # noqa: F401
14
+ from voipbin_mcp.tools import queues # noqa: F401
15
+ from voipbin_mcp.tools import routes # noqa: F401
16
+ from voipbin_mcp.tools import billings # noqa: F401
17
+ from voipbin_mcp.tools import ais # noqa: F401
18
+ from voipbin_mcp.tools import customer # noqa: F401
19
+ from voipbin_mcp.tools import tags # noqa: F401
20
+ from voipbin_mcp.tools import extensions # noqa: F401
@@ -0,0 +1,45 @@
1
+ """Active flow tools."""
2
+
3
+ from voipbin_mcp.server import mcp, get_client, format_response, validate_page_size
4
+
5
+
6
+ @mcp.tool()
7
+ async def list_activeflows(page_size: int = 10, page_token: str = "") -> str:
8
+ """List all currently running active flows.
9
+
10
+ Active flows are flow instances currently executing on calls.
11
+
12
+ Args:
13
+ page_size: Number of results per page (default 10).
14
+ page_token: Pagination cursor from a previous response.
15
+ """
16
+ client = get_client()
17
+ params = {"page_size": validate_page_size(page_size)}
18
+ if page_token:
19
+ params["page_token"] = page_token
20
+ result = await client.get("/activeflows", params=params)
21
+ return format_response(result)
22
+
23
+
24
+ @mcp.tool()
25
+ async def get_activeflow(activeflow_id: str) -> str:
26
+ """Get details of a running active flow.
27
+
28
+ Args:
29
+ activeflow_id: The UUID of the active flow.
30
+ """
31
+ client = get_client()
32
+ result = await client.get(f"/activeflows/{activeflow_id}")
33
+ return format_response(result)
34
+
35
+
36
+ @mcp.tool()
37
+ async def stop_activeflow(activeflow_id: str) -> str:
38
+ """Stop a running active flow.
39
+
40
+ Args:
41
+ activeflow_id: The UUID of the active flow to stop.
42
+ """
43
+ client = get_client()
44
+ result = await client.post(f"/activeflows/{activeflow_id}/stop")
45
+ return format_response(result)
@@ -0,0 +1,33 @@
1
+ """Agent tools."""
2
+
3
+ from voipbin_mcp.server import mcp, get_client, format_response, validate_page_size
4
+
5
+
6
+ @mcp.tool()
7
+ async def list_agents(page_size: int = 10, page_token: str = "") -> str:
8
+ """List all agents in your VoIPbin account.
9
+
10
+ Agents are users who can handle calls, messages, and other interactions.
11
+
12
+ Args:
13
+ page_size: Number of results per page (default 10).
14
+ page_token: Pagination cursor from a previous response.
15
+ """
16
+ client = get_client()
17
+ params = {"page_size": validate_page_size(page_size)}
18
+ if page_token:
19
+ params["page_token"] = page_token
20
+ result = await client.get("/agents", params=params)
21
+ return format_response(result)
22
+
23
+
24
+ @mcp.tool()
25
+ async def get_agent(agent_id: str) -> str:
26
+ """Get details of a specific agent.
27
+
28
+ Args:
29
+ agent_id: The UUID of the agent.
30
+ """
31
+ client = get_client()
32
+ result = await client.get(f"/agents/{agent_id}")
33
+ return format_response(result)