@vapi-ai/mcp-server 0.0.11 → 0.1.0

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 (53) hide show
  1. package/README.md +152 -6
  2. package/dist/knowledge/docs.d.ts +96 -0
  3. package/dist/knowledge/docs.d.ts.map +1 -0
  4. package/dist/knowledge/docs.js +16 -0
  5. package/dist/knowledge/skills.d.ts +28 -0
  6. package/dist/knowledge/skills.d.ts.map +1 -0
  7. package/dist/knowledge/skills.js +131 -0
  8. package/dist/schemas/assistant-openapi.d.ts +31 -0
  9. package/dist/schemas/assistant-openapi.d.ts.map +1 -0
  10. package/dist/schemas/assistant-openapi.js +87 -0
  11. package/dist/schemas/assistant-openapi.json +2341 -0
  12. package/dist/schemas/index.d.ts +158 -1181
  13. package/dist/schemas/index.d.ts.map +1 -1
  14. package/dist/schemas/index.js +95 -172
  15. package/dist/schemas/simulation-openapi.d.ts +9 -0
  16. package/dist/schemas/simulation-openapi.d.ts.map +1 -0
  17. package/dist/schemas/simulation-openapi.js +81 -0
  18. package/dist/schemas/simulation-openapi.json +27558 -0
  19. package/dist/schemas/simulation.d.ts +54 -0
  20. package/dist/schemas/simulation.d.ts.map +1 -0
  21. package/dist/schemas/simulation.js +76 -0
  22. package/dist/tools/api-schema.d.ts +4 -0
  23. package/dist/tools/api-schema.d.ts.map +1 -0
  24. package/dist/tools/api-schema.js +67 -0
  25. package/dist/tools/assistant.d.ts.map +1 -1
  26. package/dist/tools/assistant.js +25 -10
  27. package/dist/tools/call.d.ts.map +1 -1
  28. package/dist/tools/call.js +13 -6
  29. package/dist/tools/docs.d.ts +3 -0
  30. package/dist/tools/docs.d.ts.map +1 -0
  31. package/dist/tools/docs.js +27 -0
  32. package/dist/tools/index.d.ts.map +1 -1
  33. package/dist/tools/index.js +8 -0
  34. package/dist/tools/input-schema.d.ts +5 -0
  35. package/dist/tools/input-schema.d.ts.map +1 -0
  36. package/dist/tools/input-schema.js +59 -0
  37. package/dist/tools/phone-number.d.ts.map +1 -1
  38. package/dist/tools/phone-number.js +11 -5
  39. package/dist/tools/simulation.d.ts +4 -0
  40. package/dist/tools/simulation.d.ts.map +1 -0
  41. package/dist/tools/simulation.js +133 -0
  42. package/dist/tools/skills.d.ts +3 -0
  43. package/dist/tools/skills.d.ts.map +1 -0
  44. package/dist/tools/skills.js +31 -0
  45. package/dist/tools/tool.d.ts.map +1 -1
  46. package/dist/tools/tool.js +23 -9
  47. package/dist/tools/validation.d.ts +22 -0
  48. package/dist/tools/validation.d.ts.map +1 -0
  49. package/dist/tools/validation.js +94 -0
  50. package/dist/transformers/index.d.ts +3 -3
  51. package/dist/transformers/index.d.ts.map +1 -1
  52. package/dist/transformers/index.js +52 -31
  53. package/package.json +9 -6
@@ -0,0 +1,54 @@
1
+ import { z } from 'zod';
2
+ export declare const ListSimulationResourcesInputSchema: z.ZodObject<{
3
+ limit: z.ZodOptional<z.ZodPipe<z.ZodType<number, unknown, z.core.$ZodTypeInternals<number, unknown>>, z.ZodNumber>>;
4
+ }, z.core.$strip>;
5
+ export declare const ListSimulationScenariosInputSchema: z.ZodObject<{
6
+ limit: z.ZodOptional<z.ZodPipe<z.ZodType<number, unknown, z.core.$ZodTypeInternals<number, unknown>>, z.ZodNumber>>;
7
+ name: z.ZodOptional<z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>>;
8
+ }, z.core.$strip>;
9
+ export declare const CreateSimulationPersonalityInputSchema: z.ZodObject<{
10
+ name: z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>;
11
+ assistant: z.ZodType<Record<string, unknown>, unknown, z.core.$ZodTypeInternals<Record<string, unknown>, unknown>>;
12
+ path: z.ZodType<string | null | undefined, unknown, z.core.$ZodTypeInternals<string | null | undefined, unknown>>;
13
+ }, z.core.$strip>;
14
+ export declare const CreateSimulationScenarioInputSchema: z.ZodObject<{
15
+ name: z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>;
16
+ instructions: z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>;
17
+ evaluations: z.ZodType<Record<string, unknown>[], unknown, z.core.$ZodTypeInternals<Record<string, unknown>[], unknown>>;
18
+ path: z.ZodType<string | null | undefined, unknown, z.core.$ZodTypeInternals<string | null | undefined, unknown>>;
19
+ additionalFields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
20
+ }, z.core.$strip>;
21
+ export declare const CreateSimulationInputSchema: z.ZodObject<{
22
+ scenarioId: z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>;
23
+ personalityId: z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>;
24
+ name: z.ZodType<string | undefined, unknown, z.core.$ZodTypeInternals<string | undefined, unknown>>;
25
+ path: z.ZodType<string | null | undefined, unknown, z.core.$ZodTypeInternals<string | null | undefined, unknown>>;
26
+ }, z.core.$strip>;
27
+ export declare const CreateSimulationSuiteInputSchema: z.ZodObject<{
28
+ name: z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>;
29
+ simulationIds: z.ZodType<string[], unknown, z.core.$ZodTypeInternals<string[], unknown>>;
30
+ path: z.ZodType<string | null | undefined, unknown, z.core.$ZodTypeInternals<string | null | undefined, unknown>>;
31
+ additionalFields: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
32
+ }, z.core.$strip>;
33
+ export declare const RunSimulationsInputSchema: z.ZodObject<{
34
+ assistantId: z.ZodOptional<z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>>;
35
+ squadId: z.ZodOptional<z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>>;
36
+ simulationIds: z.ZodOptional<z.ZodArray<z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>>>;
37
+ suiteIds: z.ZodOptional<z.ZodArray<z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>>>;
38
+ iterations: z.ZodOptional<z.ZodPipe<z.ZodType<number, unknown, z.core.$ZodTypeInternals<number, unknown>>, z.ZodNumber>>;
39
+ transport: z.ZodOptional<z.ZodType<"vapi.websocket" | "vapi.webchat", unknown, z.core.$ZodTypeInternals<"vapi.websocket" | "vapi.webchat", unknown>>>;
40
+ idempotencyKey: z.ZodOptional<z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>>;
41
+ }, z.core.$strip>;
42
+ export declare const ListSimulationRunsInputSchema: z.ZodObject<{
43
+ limit: z.ZodOptional<z.ZodPipe<z.ZodType<number, unknown, z.core.$ZodTypeInternals<number, unknown>>, z.ZodNumber>>;
44
+ status: z.ZodOptional<z.ZodType<"queued" | "running" | "ended", unknown, z.core.$ZodTypeInternals<"queued" | "running" | "ended", unknown>>>;
45
+ targetId: z.ZodOptional<z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>>;
46
+ }, z.core.$strip>;
47
+ export declare const GetSimulationRunInputSchema: z.ZodObject<{
48
+ runId: z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>;
49
+ }, z.core.$strip>;
50
+ export declare const GetSimulationRunItemInputSchema: z.ZodObject<{
51
+ runId: z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>;
52
+ itemId: z.ZodType<string, unknown, z.core.$ZodTypeInternals<string, unknown>>;
53
+ }, z.core.$strip>;
54
+ //# sourceMappingURL=simulation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simulation.d.ts","sourceRoot":"","sources":["../../src/schemas/simulation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB,eAAO,MAAM,kCAAkC;;iBAAsB,CAAC;AACtE,eAAO,MAAM,kCAAkC;;;iBAE7C,CAAC;AAEH,eAAO,MAAM,sCAAsC;;;;iBAIjD,CAAC;AAEH,eAAO,MAAM,mCAAmC;;;;;;iBAQ9C,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;;;iBAKtC,CAAC;AAEH,eAAO,MAAM,gCAAgC;;;;;iBAO3C,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;iBAsBlC,CAAC;AAEL,eAAO,MAAM,6BAA6B;;;;iBAGxC,CAAC;AACH,eAAO,MAAM,2BAA2B;;iBAAkD,CAAC;AAE3F,eAAO,MAAM,+BAA+B;;;iBAE1C,CAAC"}
@@ -0,0 +1,76 @@
1
+ import { z } from 'zod';
2
+ import { simulationField as field, simulationParameter as parameter, validateSimulationBody } from './simulation-openapi.js';
3
+ // Limits of 1–100 integers and a default of 50 are the compact MCP paging
4
+ // policy; the API's imported range is 0–1000. Keep that policy explicit.
5
+ const limit = parameter('limit').pipe(z.number().int().min(1).max(100)).optional()
6
+ .describe('Maximum number of results to return (default 50)');
7
+ const additionalFields = z.record(z.string(), z.unknown()).optional()
8
+ .describe('Additional documented API fields. The merged request is validated against the bundled Vapi OpenAPI schema.');
9
+ export const ListSimulationResourcesInputSchema = z.object({ limit });
10
+ export const ListSimulationScenariosInputSchema = z.object({
11
+ limit, name: parameter('scenarioName').optional(),
12
+ });
13
+ export const CreateSimulationPersonalityInputSchema = z.object({
14
+ name: field('CreatePersonalityDTO', 'name'),
15
+ assistant: field('CreatePersonalityDTO', 'assistant'),
16
+ path: field('CreatePersonalityDTO', 'path'),
17
+ });
18
+ export const CreateSimulationScenarioInputSchema = z.object({
19
+ name: field('CreateScenarioDTO', 'name'),
20
+ instructions: field('CreateScenarioDTO', 'instructions'),
21
+ evaluations: field('CreateScenarioDTO', 'evaluations'),
22
+ path: field('CreateScenarioDTO', 'path'),
23
+ additionalFields,
24
+ }).superRefine((input, ctx) => {
25
+ if (input.additionalFields)
26
+ validateSimulationBody('CreateScenarioDTO', input, ctx);
27
+ });
28
+ export const CreateSimulationInputSchema = z.object({
29
+ scenarioId: field('CreateSimulationDTO', 'scenarioId'),
30
+ personalityId: field('CreateSimulationDTO', 'personalityId'),
31
+ name: field('CreateSimulationDTO', 'name'),
32
+ path: field('CreateSimulationDTO', 'path'),
33
+ });
34
+ export const CreateSimulationSuiteInputSchema = z.object({
35
+ name: field('CreateSimulationSuiteDTO', 'name'),
36
+ simulationIds: field('CreateSimulationSuiteDTO', 'simulationIds'),
37
+ path: field('CreateSimulationSuiteDTO', 'path'),
38
+ additionalFields,
39
+ }).superRefine((input, ctx) => {
40
+ if (input.additionalFields)
41
+ validateSimulationBody('CreateSimulationSuiteDTO', input, ctx);
42
+ });
43
+ export const RunSimulationsInputSchema = z.object({
44
+ assistantId: field('SimulationRunTargetAssistant', 'assistantId').optional(),
45
+ squadId: field('SimulationRunTargetSquad', 'squadId').optional(),
46
+ simulationIds: z.array(field('SimulationRunSimulationEntry', 'simulationId')).optional(),
47
+ suiteIds: z.array(field('SimulationRunSuiteEntry', 'simulationSuiteId')).optional(),
48
+ // The integral iteration count is an MCP adapter rule; bounds come from API.
49
+ iterations: field('CreateSimulationRunDTO', 'iterations').pipe(z.number().int()).optional(),
50
+ transport: field('SimulationRunTransportConfiguration', 'provider').optional(),
51
+ idempotencyKey: parameter('idempotencyKey').optional(),
52
+ }).superRefine((input, ctx) => {
53
+ if (!!input.assistantId === !!input.squadId)
54
+ ctx.addIssue({
55
+ code: 'custom', path: ['assistantId'], message: 'Give exactly one of assistantId or squadId.',
56
+ });
57
+ if (!(input.simulationIds?.length || input.suiteIds?.length))
58
+ ctx.addIssue({
59
+ code: 'custom', path: ['simulationIds'], message: 'Give at least one simulationId or suiteId.',
60
+ });
61
+ }).meta({ allOf: [
62
+ { oneOf: [{ required: ['assistantId'] }, { required: ['squadId'] }] },
63
+ { anyOf: [
64
+ { required: ['simulationIds'], properties: { simulationIds: { minItems: 1 } } },
65
+ { required: ['suiteIds'], properties: { suiteIds: { minItems: 1 } } },
66
+ ] },
67
+ ] });
68
+ export const ListSimulationRunsInputSchema = z.object({
69
+ limit, status: parameter('runStatus').optional(),
70
+ targetId: parameter('targetId').optional(),
71
+ });
72
+ export const GetSimulationRunInputSchema = z.object({ runId: parameter('runId') });
73
+ // The item endpoint publishes plain strings, unlike the run endpoint's UUID.
74
+ export const GetSimulationRunItemInputSchema = z.object({
75
+ runId: parameter('itemRunId'), itemId: parameter('itemId'),
76
+ });
@@ -0,0 +1,4 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { VapiClient } from '@vapi-ai/server-sdk';
3
+ export declare const registerApiSchemaTools: (server: McpServer, vapiClient: VapiClient) => void;
4
+ //# sourceMappingURL=api-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-schema.d.ts","sourceRoot":"","sources":["../../src/tools/api-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAmB,MAAM,qBAAqB,CAAC;AAkElE,eAAO,MAAM,sBAAsB,GACjC,QAAQ,SAAS,EACjB,YAAY,UAAU,SAuCvB,CAAC"}
@@ -0,0 +1,67 @@
1
+ import { VapiEnvironment } from '@vapi-ai/server-sdk';
2
+ import { GetApiSchemaInputSchema } from '../schemas/index.js';
3
+ import { createToolHandler } from './utils.js';
4
+ // The OpenAPI spec is about 2 MB, so load it once per client and keep only
5
+ // its schemas. It is fetched through the client so it comes from the same
6
+ // API environment the other tools call.
7
+ const schemaCache = new WeakMap();
8
+ // vapiClient.fetch resolves relative paths only against an explicitly
9
+ // configured base URL, so resolve it the way the SDK's own resource clients
10
+ // do: baseUrl, then environment, then the default API host.
11
+ async function resolveBaseUrl(vapiClient) {
12
+ const options = vapiClient._options;
13
+ const get = async (supplier) => typeof supplier === 'function' ? await supplier() : supplier;
14
+ return ((await get(options?.baseUrl)) ??
15
+ (await get(options?.environment)) ??
16
+ VapiEnvironment.Default);
17
+ }
18
+ function loadSchemas(vapiClient) {
19
+ let schemas = schemaCache.get(vapiClient);
20
+ if (!schemas) {
21
+ schemas = resolveBaseUrl(vapiClient)
22
+ .then((baseUrl) => vapiClient.fetch(`${baseUrl.replace(/\/+$/, '')}/api-json`))
23
+ .then(async (response) => {
24
+ if (!response.ok) {
25
+ throw new Error(`Could not load the Vapi API schema: HTTP ${response.status}`);
26
+ }
27
+ const spec = (await response.json());
28
+ return spec.components?.schemas ?? {};
29
+ });
30
+ // Let the next call retry after a failed load.
31
+ schemas.catch(() => schemaCache.delete(vapiClient));
32
+ schemaCache.set(vapiClient, schemas);
33
+ }
34
+ return schemas;
35
+ }
36
+ function findSchemaNames(schemas, text) {
37
+ const needle = text.toLowerCase();
38
+ return Object.keys(schemas)
39
+ .filter((name) => name.toLowerCase().includes(needle))
40
+ .sort();
41
+ }
42
+ const MAX_MATCHES = 50;
43
+ export const registerApiSchemaTools = (server, vapiClient) => {
44
+ server.registerTool('get_api_schema', {
45
+ description: 'Looks up a schema in the Vapi API reference (the OpenAPI spec the Vapi SDKs are generated from). ' +
46
+ 'Pass `search` to find schema names, then `name` to get one schema. ' +
47
+ 'References to other schemas are left as "#/components/schemas/<Name>" and listed in referencedSchemas, so look those up next if you need them. ' +
48
+ 'Use it to find fields that other tools accept through additionalFields.',
49
+ inputSchema: GetApiSchemaInputSchema.shape,
50
+ }, createToolHandler(async (data) => {
51
+ const schemas = await loadSchemas(vapiClient);
52
+ if (data.name) {
53
+ const schema = schemas[data.name];
54
+ if (!schema) {
55
+ const similar = findSchemaNames(schemas, data.name).slice(0, 10);
56
+ throw new Error(`No schema named ${data.name}.` +
57
+ (similar.length > 0 ? ` Similar names: ${similar.join(', ')}` : ''));
58
+ }
59
+ const referencedSchemas = [
60
+ ...new Set(Array.from(JSON.stringify(schema).matchAll(/#\/components\/schemas\/([\w.-]+)/g), (match) => match[1])),
61
+ ];
62
+ return { name: data.name, schema, referencedSchemas };
63
+ }
64
+ const matches = findSchemaNames(schemas, data.search ?? '');
65
+ return { matches: matches.slice(0, MAX_MATCHES), total: matches.length };
66
+ }));
67
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"assistant.d.ts","sourceRoot":"","sources":["../../src/tools/assistant.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAQ,MAAM,qBAAqB,CAAC;AAavD,eAAO,MAAM,sBAAsB,GACjC,QAAQ,SAAS,EACjB,YAAY,UAAU,SA6EvB,CAAC"}
1
+ {"version":3,"file":"assistant.d.ts","sourceRoot":"","sources":["../../src/tools/assistant.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAQ,MAAM,qBAAqB,CAAC;AAcvD,eAAO,MAAM,sBAAsB,GACjC,QAAQ,SAAS,EACjB,YAAY,UAAU,SA4FvB,CAAC"}
@@ -1,27 +1,34 @@
1
- import { CreateAssistantInputSchema, GetAssistantInputSchema, UpdateAssistantInputSchema, } from '../schemas/index.js';
1
+ import { registerValidatedTool } from './validation.js';
2
+ import { EmptyInputSchema, CreateAssistantInputSchema, GetAssistantInputSchema, UpdateAssistantInputSchema, } from '../schemas/index.js';
2
3
  import { transformAssistantInput, transformAssistantOutput, transformUpdateAssistantInput, } from '../transformers/index.js';
3
4
  import { createToolHandler } from './utils.js';
4
5
  export const registerAssistantTools = (server, vapiClient) => {
5
- server.registerTool('list_assistants', {
6
+ registerValidatedTool(server, 'list_assistants', {
6
7
  description: 'Lists all Vapi assistants',
7
- inputSchema: {},
8
+ inputSchema: EmptyInputSchema,
8
9
  }, createToolHandler(async () => {
9
10
  // console.log('list_assistants');
10
11
  const assistants = await vapiClient.assistants.list({ limit: 10 });
11
12
  // console.log('assistants', assistants);
12
13
  return assistants.map(transformAssistantOutput);
13
14
  }));
14
- server.tool('create_assistant', 'Creates a new Vapi assistant', CreateAssistantInputSchema.shape, createToolHandler(async (data) => {
15
+ registerValidatedTool(server, 'create_assistant', {
16
+ description: 'Creates a new Vapi assistant',
17
+ inputSchema: CreateAssistantInputSchema,
18
+ }, createToolHandler(async (data) => {
15
19
  // console.log('create_assistant', data);
16
20
  const createAssistantDto = transformAssistantInput(data);
17
21
  const assistant = await vapiClient.assistants.create(createAssistantDto);
18
22
  return transformAssistantOutput(assistant);
19
23
  }));
20
- server.tool('get_assistant', 'Gets a Vapi assistant by ID', GetAssistantInputSchema.shape, createToolHandler(async (data) => {
24
+ registerValidatedTool(server, 'get_assistant', {
25
+ description: 'Gets a Vapi assistant by ID',
26
+ inputSchema: GetAssistantInputSchema,
27
+ }, createToolHandler(async (data) => {
21
28
  // console.log('get_assistant', data);
22
29
  const assistantId = data.assistantId;
23
30
  try {
24
- const assistant = await vapiClient.assistants.get(assistantId);
31
+ const assistant = await vapiClient.assistants.get({ id: assistantId });
25
32
  if (!assistant) {
26
33
  throw new Error(`Assistant with ID ${assistantId} not found`);
27
34
  }
@@ -32,18 +39,26 @@ export const registerAssistantTools = (server, vapiClient) => {
32
39
  throw error;
33
40
  }
34
41
  }));
35
- server.tool('update_assistant', 'Updates an existing Vapi assistant', UpdateAssistantInputSchema.shape, createToolHandler(async (data) => {
42
+ registerValidatedTool(server, 'update_assistant', {
43
+ description: 'Updates an existing Vapi assistant',
44
+ inputSchema: UpdateAssistantInputSchema,
45
+ }, createToolHandler(async (data) => {
36
46
  const assistantId = data.assistantId;
37
47
  try {
38
48
  // First check if the assistant exists
39
- const existingAssistant = await vapiClient.assistants.get(assistantId);
49
+ const existingAssistant = await vapiClient.assistants.get({
50
+ id: assistantId,
51
+ });
40
52
  if (!existingAssistant) {
41
53
  throw new Error(`Assistant with ID ${assistantId} not found`);
42
54
  }
43
55
  // Transform the update data
44
- const updateAssistantDto = transformUpdateAssistantInput(data);
56
+ const updateAssistantDto = transformUpdateAssistantInput(data, existingAssistant);
45
57
  // Update the assistant
46
- const updatedAssistant = await vapiClient.assistants.update(assistantId, updateAssistantDto);
58
+ const updatedAssistant = await vapiClient.assistants.update({
59
+ ...updateAssistantDto,
60
+ id: assistantId,
61
+ });
47
62
  return transformAssistantOutput(updatedAssistant);
48
63
  }
49
64
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"call.d.ts","sourceRoot":"","sources":["../../src/tools/call.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAQ,MAAM,qBAAqB,CAAC;AASvD,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,SAAS,EACjB,YAAY,UAAU,SAkCvB,CAAC"}
1
+ {"version":3,"file":"call.d.ts","sourceRoot":"","sources":["../../src/tools/call.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAQ,MAAM,qBAAqB,CAAC;AASvD,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,SAAS,EACjB,YAAY,UAAU,SAyCvB,CAAC"}
@@ -1,21 +1,28 @@
1
- import { CallInputSchema, GetCallInputSchema } from '../schemas/index.js';
1
+ import { registerValidatedTool } from './validation.js';
2
+ import { EmptyInputSchema, CallInputSchema, GetCallInputSchema } from '../schemas/index.js';
2
3
  import { transformCallInput, transformCallOutput, } from '../transformers/index.js';
3
4
  import { createToolHandler } from './utils.js';
4
5
  export const registerCallTools = (server, vapiClient) => {
5
- server.registerTool('list_calls', {
6
+ registerValidatedTool(server, 'list_calls', {
6
7
  description: 'Lists all Vapi calls',
7
- inputSchema: {},
8
+ inputSchema: EmptyInputSchema,
8
9
  }, createToolHandler(async () => {
9
10
  const calls = await vapiClient.calls.list({ limit: 10 });
10
11
  return calls.map(transformCallOutput);
11
12
  }));
12
- server.tool('create_call', 'Creates a outbound call', CallInputSchema.shape, createToolHandler(async (data) => {
13
+ registerValidatedTool(server, 'create_call', {
14
+ description: 'Creates a outbound call',
15
+ inputSchema: CallInputSchema,
16
+ }, createToolHandler(async (data) => {
13
17
  const createCallDto = transformCallInput(data);
14
18
  const call = await vapiClient.calls.create(createCallDto);
15
19
  return transformCallOutput(call);
16
20
  }));
17
- server.tool('get_call', 'Gets details of a specific call', GetCallInputSchema.shape, createToolHandler(async (data) => {
18
- const call = await vapiClient.calls.get(data.callId);
21
+ registerValidatedTool(server, 'get_call', {
22
+ description: 'Gets details of a specific call',
23
+ inputSchema: GetCallInputSchema,
24
+ }, createToolHandler(async (data) => {
25
+ const call = await vapiClient.calls.get({ id: data.callId });
19
26
  return transformCallOutput(call);
20
27
  }));
21
28
  };
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerDocsTools(server: McpServer): void;
3
+ //# sourceMappingURL=docs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/tools/docs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAazE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,QAelD"}
@@ -0,0 +1,27 @@
1
+ import { z } from 'zod';
2
+ import { askVapiDocs } from '../knowledge/docs.js';
3
+ async function knowledgeResult(action) {
4
+ try {
5
+ return await action();
6
+ }
7
+ catch (error) {
8
+ return { isError: true, content: [{ type: 'text', text: `Knowledge request failed: ${error instanceof Error ? error.message : 'Unknown upstream error'}` }] };
9
+ }
10
+ }
11
+ export function registerDocsTools(server) {
12
+ const annotations = { readOnlyHint: true, destructiveHint: false, openWorldHint: true };
13
+ server.registerTool('ask_vapi_docs', {
14
+ description: 'Ask about current Vapi documentation through the Fern docs MCP. Returns relevant documentation passages and source URLs; use them to answer the question.',
15
+ inputSchema: {
16
+ question: z.string().trim().min(1).max(4000).describe('A specific question about Vapi configuration, APIs, SDKs or troubleshooting. Send no API keys or private customer data.'),
17
+ topK: z.number().int().min(1).max(20).default(8).describe('Maximum number of relevant documentation passages.'),
18
+ }, annotations,
19
+ }, ({ question, topK }, extra) => knowledgeResult(async () => {
20
+ const result = await askVapiDocs(question, topK, extra.signal);
21
+ // The upstream SDK also types legacy toolResult responses. Fern uses the
22
+ // normal content form, which is the only form this wrapper advertises.
23
+ if (!('content' in result))
24
+ throw new Error('Unexpected response from the Vapi docs MCP.');
25
+ return result;
26
+ }));
27
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAOjD,eAAO,MAAM,gBAAgB,GAAI,QAAQ,SAAS,EAAE,YAAY,UAAU,SAKzE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAWjD,eAAO,MAAM,gBAAgB,GAAI,QAAQ,SAAS,EAAE,YAAY,UAAU,SASzE,CAAC"}
@@ -1,10 +1,18 @@
1
+ import { registerDocsTools } from './docs.js';
1
2
  import { registerAssistantTools } from './assistant.js';
2
3
  import { registerCallTools } from './call.js';
3
4
  import { registerPhoneNumberTools } from './phone-number.js';
5
+ import { registerSimulationTools } from './simulation.js';
4
6
  import { registerToolTools } from './tool.js';
7
+ import { registerSkillTools } from './skills.js';
8
+ import { registerApiSchemaTools } from './api-schema.js';
5
9
  export const registerAllTools = (server, vapiClient) => {
10
+ registerDocsTools(server);
6
11
  registerAssistantTools(server, vapiClient);
7
12
  registerCallTools(server, vapiClient);
8
13
  registerPhoneNumberTools(server, vapiClient);
9
14
  registerToolTools(server, vapiClient);
15
+ registerApiSchemaTools(server, vapiClient);
16
+ registerSkillTools(server);
17
+ registerSimulationTools(server, vapiClient);
10
18
  };
@@ -0,0 +1,5 @@
1
+ import type { z } from 'zod';
2
+ type JsonSchema = z.core.JSONSchema.JSONSchema;
3
+ export declare function summarizeInputSchema(schema: JsonSchema): JsonSchema;
4
+ export {};
5
+ //# sourceMappingURL=input-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-schema.d.ts","sourceRoot":"","sources":["../../src/tools/input-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,KAAK,UAAU,GAAG,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;AAM/C,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,CAsCnE"}
@@ -0,0 +1,59 @@
1
+ // tools/list describes how to call a tool. Provider catalogs and recursive API
2
+ // definitions belong in on-demand schema lookup, not every agent's tool context.
3
+ // This projection is intentionally broader than the unchanged runtime validator.
4
+ export function summarizeInputSchema(schema) {
5
+ const alternatives = schema.oneOf ?? schema.anyOf;
6
+ if (alternatives?.length && alternatives.every(branch => branch.type === 'object' && branch.properties?.provider)) {
7
+ const keys = [...new Set(alternatives.flatMap(branch => Object.keys(branch.properties)))];
8
+ return {
9
+ type: 'object',
10
+ properties: Object.fromEntries(keys.map(key => [key, typeSummary(alternatives.flatMap(branch => branch.properties?.[key] ? [branch.properties[key]] : []))])),
11
+ required: (alternatives[0].required ?? []).filter(key => alternatives.every(branch => branch.required?.includes(key))),
12
+ additionalProperties: false,
13
+ ...(schema.description ? { description: schema.description } : {}),
14
+ };
15
+ }
16
+ // Do not expand recursive JSON Schema definitions in the advertised contract.
17
+ // An empty schema accepts the value; the runtime validator still checks it.
18
+ if (schema.$ref)
19
+ return {};
20
+ const summary = {};
21
+ for (const [key, value] of Object.entries(schema)) {
22
+ // Dropping a negative constraint broadens discovery; simplifying its
23
+ // contents could instead reject values accepted by the runtime schema.
24
+ if (['definitions', '$defs', '$schema', 'title', 'example', 'examples', 'not'].includes(key))
25
+ continue;
26
+ if (key === 'description' && typeof value === 'string' && value.length > 180)
27
+ continue;
28
+ if (key === 'enum' && Array.isArray(value) && value.length > 8)
29
+ continue;
30
+ if (key === 'properties') {
31
+ summary.properties = Object.fromEntries(Object.entries(value)
32
+ .map(([name, field]) => [name, typeof field === 'boolean' ? field : summarizeInputSchema(field)]));
33
+ }
34
+ else if (['oneOf', 'anyOf', 'allOf'].includes(key)) {
35
+ // Relaxed branches can overlap, so discovery must not require exclusivity.
36
+ summary[key === 'oneOf' ? 'anyOf' : key] = value.map(summarizeInputSchema);
37
+ }
38
+ else if (['items', 'additionalProperties', 'then', 'else'].includes(key) && typeof value === 'object' && value !== null) {
39
+ summary[key] = summarizeInputSchema(value);
40
+ }
41
+ else {
42
+ summary[key] = value;
43
+ }
44
+ }
45
+ return summary;
46
+ }
47
+ function typeSummary(schemas) {
48
+ if (schemas.some(schema => typeof schema === 'boolean' || !schemaTypes(schema).length))
49
+ return {};
50
+ const types = [...new Set(schemas.flatMap(schemaTypes))];
51
+ return types.length === 1 ? { type: types[0] } : types.length ? { type: types } : {};
52
+ }
53
+ function schemaTypes(schema) {
54
+ if (typeof schema === 'boolean')
55
+ return [];
56
+ if (schema.type)
57
+ return Array.isArray(schema.type) ? schema.type : [schema.type];
58
+ return (schema.oneOf ?? schema.anyOf ?? []).flatMap(schemaTypes);
59
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"phone-number.d.ts","sourceRoot":"","sources":["../../src/tools/phone-number.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAMjD,eAAO,MAAM,wBAAwB,GACnC,QAAQ,SAAS,EACjB,YAAY,UAAU,SAwBvB,CAAC"}
1
+ {"version":3,"file":"phone-number.d.ts","sourceRoot":"","sources":["../../src/tools/phone-number.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAMjD,eAAO,MAAM,wBAAwB,GACnC,QAAQ,SAAS,EACjB,YAAY,UAAU,SA8BvB,CAAC"}
@@ -1,17 +1,23 @@
1
+ import { registerValidatedTool } from './validation.js';
1
2
  import { transformPhoneNumberOutput } from '../transformers/index.js';
2
3
  import { createToolHandler } from './utils.js';
3
- import { GetPhoneNumberInputSchema } from '../schemas/index.js';
4
+ import { EmptyInputSchema, GetPhoneNumberInputSchema } from '../schemas/index.js';
4
5
  export const registerPhoneNumberTools = (server, vapiClient) => {
5
- server.registerTool('list_phone_numbers', {
6
+ registerValidatedTool(server, 'list_phone_numbers', {
6
7
  description: 'Lists all Vapi phone numbers',
7
- inputSchema: {},
8
+ inputSchema: EmptyInputSchema,
8
9
  }, createToolHandler(async () => {
9
10
  const phoneNumbers = await vapiClient.phoneNumbers.list({ limit: 10 });
10
11
  return phoneNumbers.map(transformPhoneNumberOutput);
11
12
  }));
12
- server.tool('get_phone_number', 'Gets details of a specific phone number', GetPhoneNumberInputSchema.shape, createToolHandler(async (data) => {
13
+ registerValidatedTool(server, 'get_phone_number', {
14
+ description: 'Gets details of a specific phone number',
15
+ inputSchema: GetPhoneNumberInputSchema,
16
+ }, createToolHandler(async (data) => {
13
17
  const phoneNumberId = data.phoneNumberId;
14
- const phoneNumber = await vapiClient.phoneNumbers.get(phoneNumberId);
18
+ const phoneNumber = await vapiClient.phoneNumbers.get({
19
+ id: phoneNumberId,
20
+ });
15
21
  return transformPhoneNumberOutput(phoneNumber);
16
22
  }));
17
23
  };
@@ -0,0 +1,4 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { VapiClient } from '@vapi-ai/server-sdk';
3
+ export declare const registerSimulationTools: (server: McpServer, vapiClient: VapiClient) => void;
4
+ //# sourceMappingURL=simulation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simulation.d.ts","sourceRoot":"","sources":["../../src/tools/simulation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAQ,MAAM,qBAAqB,CAAC;AA2CvD,eAAO,MAAM,uBAAuB,GAClC,QAAQ,SAAS,EACjB,YAAY,UAAU,SA6NvB,CAAC"}