@jambonz/mcp-schema-server 0.1.1 → 0.1.2

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.
package/AGENTS.md CHANGED
@@ -71,17 +71,34 @@ Individual verb schemas are in `schema/verbs/`. Shared component types (synthesi
71
71
  - **answer** — Explicitly answer the call.
72
72
  - **leave** — Leave a conference or queue.
73
73
 
74
+ ### Verb synonyms
75
+ - **listen** and **stream** are synonyms - but use "stream" always when generating application code.
74
76
  ## Using the @jambonz/sdk
75
77
 
76
78
  **IMPORTANT**: Always use the `@jambonz/sdk` package (version 0.1.x+) to build jambonz applications. The older packages `@jambonz/node-client-ws` and `@jambonz/node-client` are **deprecated and replaced** by `@jambonz/sdk`. Do NOT use those old packages. Do NOT build apps with raw JSON verb arrays and plain Express/WS — use `@jambonz/sdk`.
77
79
 
80
+ **IMPORTANT — App Environment Variables vs process.env**: jambonz applications should NEVER use `process.env` for application-configurable values (phone numbers, API keys, language preferences, greeting text, etc.). Instead, use **jambonz application environment variables** — a two-step pattern:
81
+ 1. **Declare** the variables so the jambonz portal can discover them (via `envVars` option for WebSocket, or `envVarsMiddleware` for webhook).
82
+ 2. **Read** the values at runtime from the call payload (`session.data.env_vars` for WebSocket, `req.body.env_vars` for webhook).
83
+
84
+ Both steps are required. Declaring without reading means values are ignored. Reading without declaring means the portal won't know about them and won't send them. See the [Application Environment Variables](#application-environment-variables) section for full details.
85
+
78
86
  Install: `npm install @jambonz/sdk`
79
87
 
88
+ **Dependencies**: Webhook apps also require `express` (`npm install express`). WebSocket apps have no additional dependencies — the SDK includes `ws` internally. When generating a `package.json`, always include all required dependencies.
89
+
80
90
  ### Webhook Application (HTTP)
81
91
 
82
92
  Import `WebhookResponse` from `@jambonz/sdk/webhook`. Create an Express server, construct a `WebhookResponse` for each request, chain verb methods, and return it via `res.json()`.
83
93
 
84
- **Important**: Every webhook app must include a `POST /call-status` handler. jambonz sends call status change notifications (ringing, in-progress, completed, etc.) to this endpoint. The handler should log the event and return 200.
94
+ **Best practice**: Always include a `POST /call-status` handler. jambonz sends call status change notifications (ringing, in-progress, completed, etc.) to this endpoint. The handler should log the event and return 200. The path `/call-status` is conventional but the user may choose a different path:
95
+
96
+ ```typescript
97
+ app.post('/call-status', (req, res) => {
98
+ console.log(`Call ${req.body.call_sid} status: ${req.body.call_status}`);
99
+ res.sendStatus(200);
100
+ });
101
+ ```
85
102
 
86
103
  ```typescript
87
104
  import express from 'express';
@@ -348,11 +365,16 @@ When a verb completes, jambonz invokes the `actionHook` URL (webhook) or sends a
348
365
 
349
366
  ## Application Environment Variables
350
367
 
351
- Applications can declare configurable parameters that the jambonz portal discovers via an HTTP `OPTIONS` request. The portal renders a UI form from the schema, and configured values are delivered as `env_vars` in the initial call payload.
368
+ jambonz has a built-in mechanism for application configuration that is **always preferred over `process.env`**. It works in two required steps:
369
+
370
+ 1. **Declare** — Your app declares its configurable parameters with a schema. The jambonz portal discovers these via an HTTP `OPTIONS` request and renders a configuration form for administrators.
371
+ 2. **Receive** — When a call arrives, jambonz delivers the configured values in the call payload as `env_vars`. Your app reads them from there.
372
+
373
+ **IMPORTANT**: Both steps are required. If you only declare without reading, the values are ignored. If you only read without declaring, the portal won't discover the parameters and won't send them. NEVER use `process.env` for values that should be configurable per-application in the jambonz portal.
352
374
 
353
- **When to suggest env vars**: If the user describes an application that includes values likely to change between deployments or users — such as phone numbers to dial, API keys, language preferences, greeting text, queue names, or timeout values proactively ask whether they'd like to make those configurable via environment variables rather than hardcoding them. Many users won't think of this but will benefit from the flexibility.
375
+ **When to use env vars**: Phone numbers to dial, API keys, language/voice preferences, greeting text, queue names, timeout values, feature flags, or any value that might change between deployments or users. If in doubt, make it an env var.
354
376
 
355
- ### Declaring Environment Variables
377
+ ### Step 1: Define the Schema
356
378
 
357
379
  Define a schema object where each key is a parameter name and the value describes its type and UI behavior:
358
380
 
@@ -361,46 +383,81 @@ const envVars = {
361
383
  API_KEY: { type: 'string', description: 'Your API key', required: true, obscure: true },
362
384
  LANGUAGE: { type: 'string', description: 'TTS language', default: 'en-US', enum: ['en-US', 'es-ES', 'fr-FR'] },
363
385
  MAX_RETRIES: { type: 'number', description: 'Max retry attempts', default: 3 },
386
+ CARRIER: { type: 'string', description: 'Outbound carrier', jambonzResource: 'carriers' },
387
+ SYSTEM_PROMPT: { type: 'string', description: 'LLM system prompt', uiHint: 'textarea' },
388
+ TLS_CERT: { type: 'string', description: 'TLS certificate', uiHint: 'filepicker' },
364
389
  };
365
390
  ```
366
391
 
367
- Each parameter supports: `type` (required: `'string'` | `'number'` | `'boolean'`), `description` (required), `required`, `default`, `enum`, and `obscure` (masks value in portal UI for secrets).
392
+ Each parameter supports:
368
393
 
369
- ### WebSocket Apps
394
+ | Property | Required | Description |
395
+ |----------|----------|-------------|
396
+ | `type` | Yes | `'string'` \| `'number'` \| `'boolean'` |
397
+ | `description` | Yes | Human-readable label shown in the portal |
398
+ | `required` | No | Whether the user must provide a value |
399
+ | `default` | No | Pre-filled default value |
400
+ | `enum` | No | Array of allowed values — renders as a dropdown |
401
+ | `obscure` | No | Masks the value in the portal UI (for secrets/API keys) |
402
+ | `uiHint` | No | `'input'` (default single-line), `'textarea'` (multi-line), or `'filepicker'` (file upload with textarea) |
403
+ | `jambonzResource` | No | Populate a dropdown from jambonz account data. Currently supports `'carriers'` (lists VoIP carriers on the account) |
370
404
 
371
- Pass `envVars` to `createEndpoint`. The SDK auto-responds to OPTIONS requests:
405
+ **Notes on `jambonzResource`**: When set to `'carriers'`, the portal fetches the VoIP carriers configured for the account and renders them as a dropdown. The stored value is the carrier name. This is preferred over hardcoding carrier names or using `enum` with static values.
372
406
 
373
- ```typescript
374
- const makeService = createEndpoint({ server, port: 3000, envVars });
375
- ```
407
+ ### Step 2: Register and Read — WebSocket Apps
376
408
 
377
- Access values at runtime via `session.data`:
409
+ Pass `envVars` to `createEndpoint` to register the declaration (the SDK auto-responds to OPTIONS requests), then read values from `session.data.env_vars`:
378
410
 
379
411
  ```typescript
412
+ import http from 'http';
413
+ import { createEndpoint } from '@jambonz/sdk/websocket';
414
+
415
+ const envVars = {
416
+ GREETING: { type: 'string', description: 'Greeting message', default: 'Hello!' },
417
+ LANGUAGE: { type: 'string', description: 'TTS language', default: 'en-US' },
418
+ };
419
+
420
+ const server = http.createServer();
421
+ const makeService = createEndpoint({ server, port: 3000, envVars }); // Step 1: declare
422
+
423
+ const svc = makeService({ path: '/' });
424
+
380
425
  svc.on('session:new', (session) => {
381
- const apiKey = session.data.env_vars?.API_KEY;
426
+ const greeting = session.data.env_vars?.GREETING || 'Hello!'; // Step 2: read
427
+ const language = session.data.env_vars?.LANGUAGE || 'en-US';
428
+
429
+ session.say({ text: greeting, language }).hangup().send();
382
430
  });
383
431
  ```
384
432
 
385
- ### Webhook Apps
433
+ ### Step 2: Register and Read — Webhook Apps
386
434
 
387
- Use the `envVarsMiddleware` to auto-respond to OPTIONS requests:
435
+ Use `envVarsMiddleware` to register the declaration (auto-responds to OPTIONS requests), then read values from `req.body.env_vars`:
388
436
 
389
437
  ```typescript
438
+ import express from 'express';
390
439
  import { WebhookResponse, envVarsMiddleware } from '@jambonz/sdk/webhook';
391
440
 
392
- app.use(envVarsMiddleware(envVars));
393
- ```
441
+ const envVars = {
442
+ GREETING: { type: 'string', description: 'Greeting message', default: 'Hello!' },
443
+ LANGUAGE: { type: 'string', description: 'TTS language', default: 'en-US' },
444
+ };
394
445
 
395
- Access values at runtime via `req.body`:
446
+ const app = express();
447
+ app.use(express.json());
448
+ app.use(envVarsMiddleware(envVars)); // Step 1: declare
396
449
 
397
- ```typescript
398
450
  app.post('/incoming', (req, res) => {
399
- const apiKey = req.body.env_vars?.API_KEY;
451
+ const greeting = req.body.env_vars?.GREETING || 'Hello!'; // Step 2: read
452
+ const language = req.body.env_vars?.LANGUAGE || 'en-US';
453
+
454
+ const jambonz = new WebhookResponse();
455
+ jambonz.say({ text: greeting, language }).hangup();
456
+ res.json(jambonz);
400
457
  });
401
458
  ```
402
459
 
403
- **Note**: `env_vars` is only present in the initial call webhook, not in subsequent actionHook callbacks.
460
+ **Note**: `env_vars` is only present in the initial call webhook (or `session:new` for WebSocket), not in subsequent actionHook callbacks. If you need env var values in actionHook handlers, store them in a variable during the initial call.
404
461
 
405
462
  ## Mid-Call Control
406
463
 
@@ -0,0 +1,8 @@
1
+ ## Generating ringback tones with tone_stream
2
+
3
+ The `dialMusic` property is an optional property that can be used to generate audio towards the A party while we are outdialing the B party and get a 180 Ringing from B. In that case, we may want to play ringback tone or a message to the A party until we gert an answer or a 183 with early media.
4
+
5
+ Besides an http(s) URL, the value can also be a FreeSWITCH `tone_stream://` URIs in addition to audio file URLs. Use the `L=` parameter to repeat the tone pattern (`L=-1` is not supported; use a finite count like `L=20`):
6
+
7
+ - **US ringback**: `tone_stream://L=20;%(2000,4000,440,480)`
8
+ - **UK ringback**: `tone_stream://L=20;%(400,200,400,450);%(400,2000,400,450)`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jambonz/mcp-schema-server",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "MCP server that provides jambonz verb schemas and documentation as resources",
5
5
  "author": "Dave Horton",
6
6
  "license": "MIT",