Skip to content

Commit 5c75bf8

Browse files
authored
Merge pull request #8 from Bandwidth/feat/host-resolution-and-hosted-defaults
SWI-10226 feat: OAuth2, live voice/messaging callbacks, hosted-mode + host resolution
2 parents dff1b10 + 5db2c33 commit 5c75bf8

47 files changed

Lines changed: 4095 additions & 547 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/test-pr.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,5 @@ jobs:
3333

3434
- name: Install Packages and Test
3535
run: |
36-
pip install -r requirements.txt
37-
pip install -r dev-requirements.txt
36+
pip install ".[dev]"
3837
python -m pytest -v

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,14 @@ venv.bak/
8585
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
8686
#.idea/
8787

88+
# OS / editor
89+
.DS_Store
90+
.obsidian/
91+
.mcp.json
92+
93+
# Serena
94+
.serena/
95+
8896
# Visual Studio Code
8997
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
9098
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore

README.md

Lines changed: 131 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,10 @@ cd mcp-server
1717
### Prerequisites
1818

1919
In order to use the Bandwidth MCP Server, you'll need the following things, set as environment variables.
20-
- Valid Bandwidth API Credentials
21-
- This will be the username and password of your Bandwidth API user
20+
- Valid Bandwidth OAuth2 Client Credentials
21+
- You will need a client ID and client secret for your Bandwidth API application
2222
- For more info on creating API credentials, see our [Credentials](https://dev.bandwidth.com/docs/credentials) page
23-
- Bandwidth Account ID
24-
- The ID of the account you'd like to make API calls on behalf of
23+
- Your account ID is auto-discovered from JWT claims after authentication — you do not need to provide it
2524

2625
### Configuration
2726

@@ -33,19 +32,24 @@ The server will respect both system environment variables and those configured v
3332
The following variables will be required to use the server:
3433

3534
```sh
36-
BW_USERNAME # Your Bandwidth API User Username
37-
BW_PASSWORD # Your Bandwidth API User Password
35+
BW_CLIENT_ID # Your Bandwidth OAuth2 client ID
36+
BW_CLIENT_SECRET # Your Bandwidth OAuth2 client secret
3837
```
3938

4039
The following variables are optional or conditionally required:
4140

4241
```sh
43-
BW_ACCOUNT_ID # Your Bandwidth Account ID. Required for most API operations.
44-
BW_NUMBER # A valid phone number on your Bandwidth account. Used with our Messaging and MFA APIs. Must be in E164 format.
45-
BW_MESSAGING_APPLICATION_ID # A Bandwidth Messaging Application ID. Used with our Messaging and MFA APIs.
46-
BW_VOICE_APPLICATION_ID # A Bandwidth Voice Application ID. Used with our MFA API.
47-
BW_MCP_TOOLS # The list of MCP tools you'd like to enable. If not set, all tools are enabled.
48-
BW_MCP_EXCLUDE_TOOLS # The list of MCP tools you'd like to exclude. Takes priority over BW_MCP_TOOLS.
42+
BW_ACCOUNT_ID # Your Bandwidth Account ID. Optional — auto-discovered from JWT claims after authentication.
43+
BW_NUMBER # A valid phone number on your Bandwidth account. Used with our Messaging API. Must be in E164 format.
44+
BW_MESSAGING_APPLICATION_ID # A Bandwidth Messaging Application ID. Used with our Messaging API.
45+
BW_VOICE_APPLICATION_ID # A Bandwidth Voice Application ID. Used to auto-configure voice callbacks in hosted mode.
46+
BW_MCP_PROFILE # Named tool preset (voice, messaging, lookup, onboarding, recordings, full). Comma-separated to combine.
47+
BW_MCP_TOOLS # Explicit tool allowlist (comma-separated operationIds). Overrides BW_MCP_PROFILE.
48+
BW_MCP_EXCLUDE_TOOLS # Explicit tool denylist (comma-separated). Takes priority over BW_MCP_TOOLS and profiles.
49+
BW_ENVIRONMENT # `test` or `uat` to target Bandwidth's test environment. Defaults to prod.
50+
BW_API_URL # API gateway override. Also serves the Dashboard XML API under /api/v2.
51+
BW_VOICE_URL # Voice API base override.
52+
BW_MESSAGING_URL # Messaging API base override.
4953
```
5054

5155
#### Including or Excluding Tools
@@ -85,6 +89,14 @@ BW_MCP_EXCLUDE_TOOLS=createLookup,getLookupStatus
8589
--exclude-tools createLookup,getLookupStatus
8690
```
8791

92+
**Account Creation Flow (Build Registration)**
93+
94+
Bandwidth Build is the free voice-first trial. Use this profile when the user has no credentials yet. The MCP only exposes `createRegistration` to kick things off — SMS verification, password set, and API credential generation all happen in pages Bandwidth links the user to. The agent shouldn't try to consume the SMS code over the API; it belongs to the user's browser flow.
95+
96+
```sh
97+
BW_MCP_TOOLS=createRegistration
98+
```
99+
88100
## Using the Server
89101

90102
Below you'll find instructions for using our MCP server with different common AI agents, as well as instructions for running the server locally. For usage with AI agents, it is recommended to use a combination of [uv](https://github.com/astral-sh/uv?tab=readme-ov-file#uv) and environment variables to start and configure the server respectively.
@@ -131,8 +143,8 @@ Then follow the prompts like the example below.
131143
"command":"uvx",
132144
"args": ["--from", "/path/to/mcp-server", "start"],
133145
"env": {
134-
"BW_USERNAME": "<insert-bw-username>",
135-
"BW_PASSWORD": "<insert-bw-password>",
146+
"BW_CLIENT_ID": "<insert-bw-client-id>",
147+
"BW_CLIENT_SECRET": "<insert-bw-client-secret>",
136148
"BW_MCP_TOOLS": "tools,to,enable",
137149
"BW_MCP_EXCLUDE_TOOLS": "tools,to,exclude",
138150
}
@@ -161,8 +173,8 @@ uvx --from /path/to/mcp-server start
161173
"command": "uvx",
162174
"args": ["--from", "/path/to/mcp-server", "start"],
163175
"env": {
164-
"BW_USERNAME": "<insert-bw-username>",
165-
"BW_PASSWORD": "<insert-bw-password>",
176+
"BW_CLIENT_ID": "<insert-bw-client-id>",
177+
"BW_CLIENT_SECRET": "<insert-bw-client-secret>",
166178
"BW_MCP_TOOLS": "tools,to,enable",
167179
"BW_MCP_EXCLUDE_TOOLS": "tools,to,exclude",
168180
}
@@ -186,8 +198,8 @@ uvx --from /path/to/mcp-server start
186198
"command": "uvx",
187199
"args": ["--from", "/path/to/mcp-server", "start"],
188200
"env": {
189-
"BW_USERNAME": "<insert-bw-username>",
190-
"BW_PASSWORD": "<insert-bw-password>",
201+
"BW_CLIENT_ID": "<insert-bw-client-id>",
202+
"BW_CLIENT_SECRET": "<insert-bw-client-secret>",
191203
"BW_MCP_TOOLS": "tools,to,enable",
192204
"BW_MCP_EXCLUDE_TOOLS": "tools,to,exclude",
193205
}
@@ -212,11 +224,11 @@ Once these are installed, create a virtual environment using:
212224
python -m venv .venv
213225
```
214226

215-
Then activate and install the required packaged from the `requirements.txt` file.
227+
Then activate and install the project with its dependencies.
216228

217229
```sh
218230
source .venv/bin/activate
219-
pip install -r requirements.txt
231+
pip install .
220232
```
221233

222234
After all packages are installed in the virtual environment, you can run the server locally using:
@@ -234,68 +246,104 @@ then you can start the server by running the following command from the root dir
234246
uvx --from ./ start
235247
```
236248

249+
## Hosted Mode
250+
251+
Run the server over HTTP to enable remote access and webhook callbacks:
252+
253+
```bash
254+
BW_MCP_TRANSPORT=streamable-http \
255+
BW_MCP_PORT=8080 \
256+
BW_MCP_BASE_URL=https://your-server.example.com \
257+
BW_CLIENT_ID=your_client_id \
258+
BW_CLIENT_SECRET=your_client_secret \
259+
python src/app.py
260+
```
261+
262+
### Local Callback Tunnel (dev only)
263+
264+
Voice and messaging callbacks need Bandwidth to reach your server over a public
265+
URL. In production you set `BW_MCP_BASE_URL`. For local development, set
266+
`BW_MCP_DEV_TUNNEL=1` and the server will open an ephemeral
267+
[`cloudflared`](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/)
268+
tunnel, use the resulting `*.trycloudflare.com` URL as `BW_MCP_BASE_URL`, and
269+
auto-wire your voice app's callbacks to it — no ngrok needed.
270+
271+
```bash
272+
BW_MCP_TRANSPORT=streamable-http \
273+
BW_MCP_DEV_TUNNEL=1 \
274+
BW_CLIENT_ID=your_client_id \
275+
BW_CLIENT_SECRET=your_client_secret \
276+
python src/app.py
277+
```
278+
279+
Requires `cloudflared` on your PATH (`brew install cloudflared` on macOS). If
280+
it's missing, the server logs a warning and starts without a tunnel. This is
281+
for **development and testing only** — production deployments should use a real
282+
host via `BW_MCP_BASE_URL`. The tunnel never starts unless `BW_MCP_DEV_TUNNEL`
283+
is set.
284+
285+
### Tool Profiles
286+
287+
Reduce context window pressure with named presets:
288+
289+
```bash
290+
BW_MCP_PROFILE=messaging # SMS/MMS tools only
291+
BW_MCP_PROFILE=voice # Voice + BXML tools
292+
BW_MCP_PROFILE=onboarding # Account creation
293+
BW_MCP_PROFILE=lookup # Number intelligence
294+
BW_MCP_PROFILE=messaging,voice # Combine profiles
295+
```
296+
297+
Profiles set via `BW_MCP_PROFILE` env var or `--profile` CLI flag. Use `BW_MCP_TOOLS` to override with specific tool names.
298+
237299
## Tools List
238300

239-
## **Multi-Factor Authentication (MFA)**
240-
- `generateMessagingCode` - Send MFA code via SMS
241-
- `generateVoiceCode` - Send MFA code via voice call
242-
- `verifyCode` - Verify a previously sent MFA code
243-
244-
## **Phone Number Lookup**
245-
- `createLookup` - Create a phone number lookup request
246-
- `getLookupStatus` - Get status of an existing lookup request
247-
248-
## **Voice & Call Management**
249-
- `listCalls` - Returns a list of call events with filtering options
250-
- `listCall` - Returns details for a single call event
251-
252-
## **Reporting & Analytics**
253-
- `getReports` - Get history of created reports
254-
- `createReport` - Create a new report instance
255-
- `getReportStatus` - Get status of a report
256-
- `getReportFile` - Download report file
257-
- `getReportDefinitions` - Get available report definitions
258-
259-
## **Media Management**
260-
- `listMedia` - List your media files
261-
- `getMedia` - Download a specific media file
262-
- `uploadMedia` - Upload a media file
263-
- `deleteMedia` - Delete a media file
264-
265-
## **Messaging**
266-
- `listMessages` - List messages with filtering options
267-
- `createMessage` - Send SMS/MMS messages
268-
- `createMultiChannelMessage` - Send multi-channel messages (RBM, SMS, MMS)
269-
270-
## **Address Management**
271-
- `getAddressFields` - Get supported address fields by country
272-
- `validateAddress` - Validate an address and get excluded features
273-
- `listAddresses` - List all addresses
274-
- `createAddress` - Create an address
275-
- `getAddress` - Get an address by ID
276-
- `updateAddress` - Update an address
277-
- `listCityInfo` - List city info search results
278-
279-
## **Compliance**
280-
- `listDocumentTypes` - List all accepted document types and metadata requirements
281-
- `listEndUserTypes` - List all End user types and accepted metadata
282-
- `listEndUserActivationRequirements` - List requirements for End user activation
283-
- `getComplianceDocumentMetadata` - Get metadata of uploaded documents
284-
- `updateComplianceDocument` - Modify document data and file
285-
- `downloadComplianceDocuments` - Download document using document ID
286-
- `createComplianceDocument` - Upload a document with metadata
287-
- `listComplianceEndUsers` - List all End users of an account
288-
- `createComplianceEndUser` - Create an End user
289-
- `getComplianceEndUser` - Retrieve an End User by ID
290-
- `updateComplianceEndUser` - Update End user details
291-
292-
## **Requirements Packages**
293-
- `listRequirementsPackages` - List all requirements packages
294-
- `createRequirementsPackage` - Create a requirements package
295-
- `getRequirementsPackage` - Retrieve a requirements package
296-
- `patchRequirementsPackage` - Update Requirements package
297-
- `getRequirementsPackageAssets` - Get assets attached to requirements package
298-
- `attachRequirementsPackageAsset` - Attach an asset to requirements package
299-
- `detachRequirementsPackageAsset` - Detach an asset from requirements package
300-
- `validateNumberActivation` - Validate number activation requirements
301-
- `getRequirementsPackageHistory` - Get history of a requirements package
301+
Tools are grouped into profiles that mirror the workflows you'd use the server for.
302+
Loading a single profile keeps your agent's context small. The full agent reference
303+
— including auth model, error codes, and the "trust nothing" guidance for async
304+
calls — lives in [`src/specs/AGENTS.md`](src/specs/AGENTS.md).
305+
306+
The default tool set is `voice` + `messaging` + `lookup` (plus
307+
`setCredentials` / `clearCredentials`, always loaded). Override with
308+
`BW_MCP_PROFILE`, `BW_MCP_TOOLS`, or `BW_MCP_EXCLUDE_TOOLS`.
309+
310+
### Session management (always loaded)
311+
- `setCredentials` — authenticate the session (stdio transport only)
312+
- `clearCredentials` — log out of the session
313+
314+
### Profile: `onboarding` (no auth required)
315+
Kicks off a new Bandwidth Build account. Only one tool is exposed — SMS verification, password set, and API credential generation all happen in the user's browser. The agent hands off after the kickoff.
316+
- `createRegistration` — submit contact details; Bandwidth then SMSes an OTP and emails a password-set link
317+
318+
### Profile: `voice`
319+
- `listApplications` / `createApplication` — find or create a voice app
320+
- `listPhoneNumbers` — find numbers on the account
321+
- `createCall` — place an outbound call
322+
- `getCallState` — read current call state (always poll after `createCall`)
323+
- `listCalls` — list call events with filtering
324+
- `updateCall` / `updateCallBxml` — redirect, hang up, or replace BXML
325+
- `generateBXML` — build valid BXML from a verb list
326+
- `respondToCallback` — queue a BXML response for an active callback (first-write-wins)
327+
- `getCallbackEvents` — read recent voice / messaging callback events
328+
- `configureCallbacks` — point an application's webhook URLs at this server
329+
330+
### Profile: `messaging`
331+
- `createMessage` — send SMS / MMS
332+
- `listMessages` — query message history
333+
- `getInboundMessages` — read inbound messages captured by this server
334+
- `listMedia` / `getMedia` / `uploadMedia` / `deleteMedia` — manage MMS media
335+
- `configureCallbacks` — point an application's callbacks at this server
336+
337+
### Profile: `lookup`
338+
- `createSyncLookup` — one-shot lookup for a small input set
339+
- `createAsyncBulkLookup` — kick off a bulk lookup
340+
- `getAsyncBulkLookup` — poll a bulk lookup
341+
342+
### Profile: `recordings`
343+
- `listCallRecordings` / `getCallRecording` — list / inspect recordings
344+
- `downloadCallRecording` — download the media
345+
- `deleteRecording` — remove a recording
346+
- `transcribeCallRecording` / `getRecordingTranscription` — request and read transcription
347+
348+
See [`src/specs/AGENTS.md`](src/specs/AGENTS.md) for argument-level guidance, polling
349+
patterns, and the structured error shape the server returns on failure.

common_use_cases.md

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41,25 +41,6 @@ BW_MCP_TOOLS=createLookup,getLookupStatus
4141
--tools createLookup,getLookupStatus
4242
```
4343

44-
## Utilizing our MFA Service
45-
46-
To create and verify multi-factor authentication codes, you'll need our three MFA tools.
47-
- `generateMessagingCode` - Used to generate and send an MFA code via SMS
48-
- `generateVoiceCode` - Use to generate and send an MFA code via a phone call
49-
- `verifyCode` - Verify an MFA code sent with one of the previous tools
50-
51-
Generating Messaging and Voice codes requires the `BW_MESSAGING_APPLICATION_ID` and `BW_VOICE_APPLICATION_ID` environment variables respectively.
52-
Both of these tools also require `BW_ACCOUNT_ID` and `BW_NUMBER`.
53-
54-
**Enabling these tools**
55-
```sh
56-
# Environment Variable
57-
BW_MCP_TOOLS=generateMessagingCode,generateVoiceCode,verifyCode
58-
59-
# CLI Flag
60-
--tools generateMessagingCode,generateVoiceCode,verifyCode
61-
```
62-
6344
## Adding a Business End User
6445

6546
To add an end user, you'll need three specific Compliance endpoints.

dev-requirements.txt

Lines changed: 0 additions & 4 deletions
This file was deleted.

pyproject.toml

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "bw-mcp-server"
3-
version = "0.1.0"
3+
version = "0.3.0"
44
description = "Bandwidth MCP Server"
55
authors = [
66
{name = "Bandwidth", email = "dx@bandwidth.com"}
@@ -9,16 +9,32 @@ readme = "README.md"
99
requires-python = ">=3.10"
1010
dependencies = [
1111
"httpx~=0.28.0",
12-
"fastmcp~=2.13.0",
13-
"mcp~=1.23.0",
12+
"fastmcp~=3.2",
13+
"mcp~=1.24",
1414
"pyyaml~=6.0.0",
1515
"werkzeug>=3.1.4"
1616
]
1717

1818
[project.scripts]
1919
start = "app:main"
2020

21-
[dependency-groups]
21+
[tool.setuptools]
22+
py-modules = [
23+
"app", "config", "servers", "server_utils", "resources",
24+
"instructions", "profiles", "oauth", "event_store", "callbacks", "tunnel",
25+
]
26+
packages = ["specs", "tools"]
27+
28+
[tool.setuptools.package-dir]
29+
"" = "src"
30+
31+
[tool.setuptools.package-data]
32+
specs = ["*.yml", "*.md"]
33+
34+
[tool.pytest.ini_options]
35+
pythonpath = ["."]
36+
37+
[project.optional-dependencies]
2238
dev = [
2339
"black>=25.1.0",
2440
"pytest>=8.4.1",

requirements.txt

Lines changed: 0 additions & 5 deletions
This file was deleted.

0 commit comments

Comments
 (0)