At this stage, the code is known to work and has been thoroughly tested

This commit is contained in:
Jason Thistlethwaite
2026-04-27 22:24:04 +00:00
parent a11fa3b142
commit 16feb51b12
15 changed files with 2899 additions and 0 deletions
+161
View File
@@ -0,0 +1,161 @@
# Library Usage
The CLI uses the same client class that application code can use directly.
```php
<?php
require __DIR__ . '/../src/VoipMsClient.php';
use VoipMs\VoipMsClient;
$client = new VoipMsClient(
getenv('VOIPMS_API_USERNAME'),
getenv('VOIPMS_API_PASSWORD'),
);
$response = $client->getPhonebookGroups();
if (!$response->successful()) {
throw new RuntimeException($response->message() ?? 'VoIP.ms request failed.');
}
foreach ($response->data()['phonebook_groups'] ?? [] as $group) {
echo $group['phonebook_group'] . ' ' . $group['name'] . PHP_EOL;
}
```
If a command does not have a convenience method yet, use the generic request method:
```php
$response = $client->request('getDIDsInfo', ['did' => '5551234567']);
```
For backwards compatibility with the CLI, `call()` still returns the older array shape:
```php
$result = $client->call('getBalance');
echo $result['raw'];
```
## Convenience Methods
General:
```php
$client->getBalance();
$client->getBalance(advanced: true);
$client->getDidsInfo();
$client->getDidsInfo('5551234567');
```
Phonebook:
```php
$client->getPhonebook();
$client->getPhonebookByGroup('16389');
$client->getPhonebookByGroupName('Spam');
$client->getPhonebookGroups();
$client->findPhonebookGroupByName('Spam');
$client->findOrCreatePhonebookGroup('Spam');
$client->findPhonebookEntriesByNumber('5553334444');
$client->setPhonebook([
'name' => 'Jane Smith',
'number' => '5553334444',
'group' => '16389',
]);
$client->deletePhonebook('32207');
$client->setPhonebookGroup('Spam');
$client->deletePhonebookGroup('16389');
```
To add a number to a named group without creating duplicate entries:
```php
$result = $client->addNumberToPhonebookGroup(
number: '5553334444',
groupName: 'Spam',
name: 'Spam Caller',
note: 'Marked by automation',
);
if ($result->changed()) {
echo 'Added entry IDs: ' . implode(', ', $result->addedEntryIds()) . PHP_EOL;
}
```
The helper creates the group if needed, reuses existing phonebook entries for
the same number when possible, and only creates a new phonebook entry when the
number does not already exist.
Removing a number from a group is a group membership update. VoIP.ms stores
group members as phonebook entry IDs, and it may allow duplicate phonebook
entries for the same number. The helper below removes every entry in the group
whose `number` matches, but keeps the phonebook entries themselves:
```php
$result = $client->removePhonebookNumberFromGroup('16389', '5553334444');
echo 'Removed IDs: ' . implode(', ', $result->removedEntryIds()) . PHP_EOL;
if (!$result->response()->successful()) {
throw new RuntimeException($result->response()->message() ?? 'Group update failed.');
}
```
If you already know the phonebook entry IDs to remove:
```php
$client->removePhonebookEntriesFromGroup('16389', ['32207', '32208']);
```
Only pass `deleteMatchedEntries: true` when you want to delete those phonebook
entries from the account entirely after removing them from the group:
```php
$client->removePhonebookNumberFromGroup('16389', '5553334444', deleteMatchedEntries: true);
```
Caller ID filtering:
```php
$client->getCallerIdFiltering();
$client->setCallerIdFiltering([
'callerid' => 'p:16389',
'did' => 'all',
'routing' => 'sys:busy',
'note' => 'Spam group',
]);
$client->deleteCallerIdFiltering('18915');
```
Call records and SMS:
```php
$client->getAccounts();
$client->getCallAccounts();
$client->getCdr('2026-04-01', '2026-04-20', '-4', [
'calltype' => 'incoming',
'callbilling' => 'all',
]);
$client->getCallRecordings('all', '2026-04-01', '2026-04-20');
$client->getCallRecording('100000_VoIP', '<value-from-getCallRecordings>');
$client->sendCallRecordingEmail('100000_VoIP', 'you@example.com', '<value-from-getCallRecordings>');
$client->sendSms('5551234567', '5553334444', 'Hello');
```
`getAccounts()` is a friendly alias for VoIP.ms `getCallAccounts`. It does not
list VoIP.ms portal login users. It returns account filter values such as `all`
or subaccount identifiers like `100000_VoIP`; use the returned `value` field as
the `account` argument for `getCdr()`, `getCallRecordings()`,
`getCallRecording()`, and `sendCallRecordingEmail()`.
`getCdr()` defaults to all call statuses (`answered`, `noanswer`, `busy`,
and `failed`) because the VoIP.ms API rejects requests where none of those
flags are set. Pass one or more status filters to narrow the result:
```php
$client->getCdr('2026-04-01', '2026-04-20', '-4', [
'answered' => '1',
]);
```
+125
View File
@@ -0,0 +1,125 @@
# Test MCP Server
This project includes a dependency-free HTTP JSON-RPC MCP endpoint for testing
remote-agent access to the VoIP.ms library.
It is intended for development and testing. It binds to `0.0.0.0` by default,
so use a firewall, VPN, or private network when exposing it beyond this machine.
## Start The Server
```bash
export VOIPMS_API_USERNAME='you@example.com'
export VOIPMS_API_PASSWORD='your-api-password'
export MCP_AUTH_TOKEN='choose-a-long-random-token'
./bin/serve-mcp.sh
```
Defaults:
```text
MCP_HOST=0.0.0.0
MCP_PORT=8787
MCP endpoint: http://0.0.0.0:8787/mcp
Health endpoint: http://0.0.0.0:8787/health
```
If `MCP_AUTH_TOKEN` is not set, the launcher generates one for that session.
For local unauthenticated testing only:
```bash
MCP_ALLOW_UNAUTHENTICATED=1 ./bin/serve-mcp.sh
```
The preferred authentication form is:
```text
Authorization: Bearer <MCP_AUTH_TOKEN>
```
For clients that cannot send custom headers during testing, the same token can
be passed as a query parameter:
```text
http://your-host:8787/mcp?token=<MCP_AUTH_TOKEN>
```
Prefer the `Authorization` header when the client supports it.
## Smoke Test
```bash
curl -s http://127.0.0.1:8787/health
```
Initialize:
```bash
curl -s http://127.0.0.1:8787/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MCP_AUTH_TOKEN" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"test"}}}'
```
Streamable HTTP GET probe:
```bash
curl -sN http://127.0.0.1:8787/mcp \
-H "Accept: text/event-stream" \
-H "Authorization: Bearer $MCP_AUTH_TOKEN"
```
Legacy SSE probe:
```bash
curl -sN http://127.0.0.1:8787/sse \
-H "Accept: text/event-stream" \
-H "Authorization: Bearer $MCP_AUTH_TOKEN"
```
List tools:
```bash
curl -s http://127.0.0.1:8787/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MCP_AUTH_TOKEN" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
```
Call a safe dry-run mutation:
```bash
curl -s http://127.0.0.1:8787/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $MCP_AUTH_TOKEN" \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"voipms_add_number_to_phonebook_group","arguments":{"number":"5553334444","group_name":"Spam","dry_run":true}}}'
```
## Exposed Tools
- `voipms_get_balance`
- `voipms_get_phonebook_groups`
- `voipms_get_phonebook_entries`
- `voipms_get_callerid_filters`
- `voipms_get_accounts`
- `voipms_get_call_accounts`
- `voipms_get_call_recordings`
- `voipms_get_call_recording`
- `voipms_send_call_recording_email`
- `voipms_get_call_transcript`
- `voipms_get_recent_cdr`
- `voipms_add_number_to_phonebook_group`
- `voipms_remove_number_from_phonebook_group`
Mutation tools default to `dry_run=true` and must be called with
`dry_run=false` to apply changes.
`voipms_get_call_transcript` is currently a placeholder. It is listed so remote
agents can discover that transcripts are planned, but transcription
storage/provider support has not been implemented yet.
`voipms_get_accounts` is a friendly alias for `voipms_get_call_accounts`. These
tools return account filter values for CDR and call recording tools. They do
not list VoIP.ms portal login users. Use the returned `value` field as the
`account` argument.