clawdcall-mcp 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ClawdCall
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.
package/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # ClawdCall MCP Server
2
+
3
+ Give AI agents access to ClawdCall's agent-facing phone execution API through the Model Context Protocol.
4
+
5
+ `clawdcall-mcp` exposes the confirmed ClawdCall workflow:
6
+
7
+ - send signup OTP
8
+ - verify signup OTP
9
+ - place outbound calls
10
+ - fetch call transcripts
11
+
12
+ The API base URL defaults to `https://api.clawdcall.com`.
13
+
14
+ ## Quick Start
15
+
16
+ ### 1. Add ClawdCall to your MCP client
17
+
18
+ ```json
19
+ {
20
+ "mcpServers": {
21
+ "clawdcall": {
22
+ "command": "npx",
23
+ "args": ["-y", "clawdcall-mcp"],
24
+ "env": {
25
+ "CLAWDCALL_API_KEY": "sk_live_your_key_here"
26
+ }
27
+ }
28
+ }
29
+ }
30
+ ```
31
+
32
+ `CLAWDCALL_API_KEY` is required for outbound calls and transcript retrieval. Signup OTP tools do not require an existing key.
33
+
34
+ For staging or self-hosted API routing:
35
+
36
+ ```json
37
+ {
38
+ "mcpServers": {
39
+ "clawdcall": {
40
+ "command": "npx",
41
+ "args": ["-y", "clawdcall-mcp"],
42
+ "env": {
43
+ "CLAWDCALL_API_KEY": "sk_live_your_key_here",
44
+ "CLAWDCALL_BASE_URL": "https://api.clawdcall.com"
45
+ }
46
+ }
47
+ }
48
+ }
49
+ ```
50
+
51
+ ## Example Prompts
52
+
53
+ - "Sign me up for ClawdCall and send a verification code."
54
+ - "Verify this ClawdCall OTP and tell me what credential I need to store securely."
55
+ - "Call this restaurant and ask if they have a table for two tonight."
56
+ - "Fetch the transcript for this ClawdCall call ID."
57
+
58
+ ## Tools
59
+
60
+ | Tool | Confirmed endpoint | Description |
61
+ | --- | --- | --- |
62
+ | `send_signup_otp` | `POST /cc/signup/send-otp` | Send a phone verification OTP for signup. |
63
+ | `verify_signup_otp` | `POST /cc/signup/verify-otp` | Verify the OTP and receive account/API-key details. |
64
+ | `place_outbound_call` | `POST /external/v1/agent/outbound?conversionFlag=1` | Place an outbound voice-agent call. |
65
+ | `get_call_transcript` | `GET /cc/v1/calls/{id}/transcript` | Fetch a transcript by call ID or campaign ID. |
66
+
67
+ ## Environment Variables
68
+
69
+ | Variable | Required | Default | Description |
70
+ | --- | --- | --- | --- |
71
+ | `CLAWDCALL_API_KEY` | For call/transcript tools | | ClawdCall API key. |
72
+ | `CLAWDCALL_BASE_URL` | No | `https://api.clawdcall.com` | API base URL. |
73
+
74
+ ## Development
75
+
76
+ ```bash
77
+ git clone https://github.com/dialgoodian/clawdcall-mcp.git
78
+ cd clawdcall-mcp
79
+ npm install
80
+ npm run dev
81
+ ```
82
+
83
+ Build:
84
+
85
+ ```bash
86
+ npm run build
87
+ ```
88
+
89
+ Run the built server:
90
+
91
+ ```bash
92
+ CLAWDCALL_API_KEY=sk_live_your_key_here npm start
93
+ ```
94
+
95
+ ## API Contract
96
+
97
+ This server tracks the ClawdCall agent-facing OpenAPI contract currently published by the ClawdCall UI repo:
98
+
99
+ - `POST /cc/signup/send-otp`
100
+ - `POST /cc/signup/verify-otp`
101
+ - `POST /external/v1/agent/outbound?conversionFlag=1`
102
+ - `GET /cc/v1/calls/{id}/transcript`
103
+
104
+ Do not add MCP tools for agents, number purchase, SMS, conversations, voices, or general webhooks until those routes exist in ClawdCall's API contract.
105
+
106
+ ## License
107
+
108
+ MIT
@@ -0,0 +1,28 @@
1
+ export type JsonPrimitive = string | number | boolean | null;
2
+ export type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
3
+ export type JsonObject = {
4
+ [key: string]: JsonValue | undefined;
5
+ };
6
+ export declare class ClawdCallApiError extends Error {
7
+ readonly status: number;
8
+ readonly body: string;
9
+ constructor(status: number, body: string);
10
+ }
11
+ export interface ClawdCallClientOptions {
12
+ apiKey?: string;
13
+ baseUrl?: string;
14
+ }
15
+ export declare class ClawdCallClient {
16
+ private readonly apiKey?;
17
+ private readonly baseUrl;
18
+ constructor(options: ClawdCallClientOptions);
19
+ get(path: string, query?: Record<string, string | number | boolean | undefined>, options?: RequestOptions): Promise<JsonValue>;
20
+ post(path: string, body?: JsonObject, options?: RequestOptions): Promise<JsonValue>;
21
+ patch(path: string, body?: JsonObject, options?: RequestOptions): Promise<JsonValue>;
22
+ delete(path: string, options?: RequestOptions): Promise<JsonValue>;
23
+ private request;
24
+ }
25
+ interface RequestOptions {
26
+ authenticated?: boolean;
27
+ }
28
+ export {};
package/dist/client.js ADDED
@@ -0,0 +1,64 @@
1
+ export class ClawdCallApiError extends Error {
2
+ status;
3
+ body;
4
+ constructor(status, body) {
5
+ super(`ClawdCall API request failed with status ${status}: ${body}`);
6
+ this.name = "ClawdCallApiError";
7
+ this.status = status;
8
+ this.body = body;
9
+ }
10
+ }
11
+ export class ClawdCallClient {
12
+ apiKey;
13
+ baseUrl;
14
+ constructor(options) {
15
+ this.apiKey = options.apiKey;
16
+ this.baseUrl = normalizeBaseUrl(options.baseUrl ?? "https://api.clawdcall.com");
17
+ }
18
+ async get(path, query, options) {
19
+ return this.request("GET", path, undefined, query, options);
20
+ }
21
+ async post(path, body, options) {
22
+ return this.request("POST", path, body, undefined, options);
23
+ }
24
+ async patch(path, body, options) {
25
+ return this.request("PATCH", path, body, undefined, options);
26
+ }
27
+ async delete(path, options) {
28
+ return this.request("DELETE", path, undefined, undefined, options);
29
+ }
30
+ async request(method, path, body, query, options) {
31
+ const url = new URL(`${this.baseUrl}${path.startsWith("/") ? path : `/${path}`}`);
32
+ const authenticated = options?.authenticated ?? true;
33
+ if (authenticated && !this.apiKey) {
34
+ throw new Error("CLAWDCALL_API_KEY is required for this tool");
35
+ }
36
+ if (query) {
37
+ for (const [key, value] of Object.entries(query)) {
38
+ if (value !== undefined) {
39
+ url.searchParams.set(key, String(value));
40
+ }
41
+ }
42
+ }
43
+ const response = await fetch(url, {
44
+ method,
45
+ headers: {
46
+ ...(authenticated ? { Authorization: `Bearer ${this.apiKey}` } : {}),
47
+ "Content-Type": "application/json",
48
+ "User-Agent": "clawdcall-mcp/0.1.0",
49
+ },
50
+ body: body === undefined ? undefined : JSON.stringify(body),
51
+ });
52
+ const text = await response.text();
53
+ if (!response.ok) {
54
+ throw new ClawdCallApiError(response.status, text);
55
+ }
56
+ if (!text) {
57
+ return null;
58
+ }
59
+ return JSON.parse(text);
60
+ }
61
+ }
62
+ function normalizeBaseUrl(baseUrl) {
63
+ return baseUrl.replace(/\/+$/, "");
64
+ }
@@ -0,0 +1,5 @@
1
+ export interface Config {
2
+ apiKey?: string;
3
+ baseUrl: string;
4
+ }
5
+ export declare function loadConfig(env?: NodeJS.ProcessEnv): Config;
package/dist/config.js ADDED
@@ -0,0 +1,6 @@
1
+ export function loadConfig(env = process.env) {
2
+ return {
3
+ apiKey: env.CLAWDCALL_API_KEY,
4
+ baseUrl: env.CLAWDCALL_BASE_URL ?? "https://api.clawdcall.com",
5
+ };
6
+ }
@@ -0,0 +1,7 @@
1
+ import type { JsonValue } from "./client.js";
2
+ export declare function jsonResponse(value: JsonValue): {
3
+ content: {
4
+ type: "text";
5
+ text: string;
6
+ }[];
7
+ };
package/dist/format.js ADDED
@@ -0,0 +1,10 @@
1
+ export function jsonResponse(value) {
2
+ return {
3
+ content: [
4
+ {
5
+ type: "text",
6
+ text: JSON.stringify(value, null, 2),
7
+ },
8
+ ],
9
+ };
10
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { ClawdCallClient } from "./client.js";
5
+ import { loadConfig } from "./config.js";
6
+ import { registerTools } from "./tools.js";
7
+ async function main() {
8
+ if (process.argv.includes("--help") || process.argv.includes("-h")) {
9
+ printHelp();
10
+ return;
11
+ }
12
+ const config = loadConfig();
13
+ const client = new ClawdCallClient(config);
14
+ const server = new McpServer({
15
+ name: "clawdcall",
16
+ version: "0.1.0",
17
+ });
18
+ registerTools(server, client);
19
+ const transport = new StdioServerTransport();
20
+ await server.connect(transport);
21
+ }
22
+ function printHelp() {
23
+ process.stdout.write(`clawdcall-mcp
24
+
25
+ Run a ClawdCall MCP server over stdio.
26
+
27
+ Environment:
28
+ CLAWDCALL_API_KEY API key required for call and transcript tools.
29
+ CLAWDCALL_BASE_URL Optional API base URL. Defaults to https://api.clawdcall.com.
30
+
31
+ Usage:
32
+ CLAWDCALL_API_KEY=sk_live_xxx npx clawdcall-mcp
33
+ `);
34
+ }
35
+ main().catch((error) => {
36
+ const message = error instanceof Error ? error.message : String(error);
37
+ process.stderr.write(`${message}\n`);
38
+ process.exitCode = 1;
39
+ });
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { ClawdCallClient } from "./client.js";
3
+ export declare function registerTools(server: McpServer, client: ClawdCallClient): void;
package/dist/tools.js ADDED
@@ -0,0 +1,77 @@
1
+ import { z } from "zod";
2
+ import { jsonResponse } from "./format.js";
3
+ const optionalString = z.string().min(1).optional();
4
+ export function registerTools(server, client) {
5
+ server.tool("send_signup_otp", "Send a ClawdCall signup phone verification OTP. Does not require an API key.", {
6
+ email: z.string().email(),
7
+ phone_number: z.string().min(1).describe("Human phone number to verify."),
8
+ }, async ({ email, phone_number }) => {
9
+ return jsonResponse(await client.post("/cc/signup/send-otp", {
10
+ email,
11
+ phoneNumber: phone_number,
12
+ }, { authenticated: false }));
13
+ });
14
+ server.tool("verify_signup_otp", "Verify a ClawdCall signup OTP and receive account/API-key details. Does not require an existing API key.", {
15
+ email: z.string().email(),
16
+ phone_number: z.string().min(1).describe("Human phone number used for signup."),
17
+ otp: z.string().min(1).describe("OTP code received by the human."),
18
+ }, async ({ email, phone_number, otp }) => {
19
+ return jsonResponse(await client.post("/cc/signup/verify-otp", {
20
+ email,
21
+ phoneNumber: phone_number,
22
+ otp,
23
+ }, { authenticated: false }));
24
+ });
25
+ server.tool("place_outbound_call", "Place an outbound ClawdCall agent call. Requires CLAWDCALL_API_KEY.", {
26
+ target: z.string().min(1).describe("E.164 phone number to call."),
27
+ tasks: z.string().min(1).describe("Full voice-agent instruction set for the call."),
28
+ intro_message: optionalString.describe("Optional opening line for the voice agent."),
29
+ openclaw_webhook_url: optionalString.describe("Optional OpenClaw /agent/run webhook URL for completion events."),
30
+ openclaw_webhook_authorization: optionalString.describe("Optional Authorization header value for the OpenClaw webhook."),
31
+ conversation_id: optionalString.describe("Optional OpenClaw conversation ID for event correlation."),
32
+ user_id: optionalString.describe("Optional user ID for webhook correlation."),
33
+ context: optionalString.describe("Optional extra context to include in the webhook payload."),
34
+ }, async (args) => {
35
+ return jsonResponse(await client.post("/external/v1/agent/outbound?conversionFlag=1", compact({
36
+ target: args.target,
37
+ tasks: args.tasks,
38
+ raw: args.intro_message ? { introMessage: args.intro_message } : undefined,
39
+ openclaw: buildOpenClawPayload(args),
40
+ })));
41
+ });
42
+ server.tool("get_call_transcript", "Fetch a ClawdCall transcript by call ID or campaign ID. Requires CLAWDCALL_API_KEY.", {
43
+ id: z.string().min(1).describe("Call ID or campaign ID returned by ClawdCall."),
44
+ }, async ({ id }) => {
45
+ return jsonResponse(await client.get(`/cc/v1/calls/${encodeURIComponent(id)}/transcript`));
46
+ });
47
+ }
48
+ function buildOpenClawPayload(args) {
49
+ if (!args.openclaw_webhook_url &&
50
+ !args.openclaw_webhook_authorization &&
51
+ !args.conversation_id &&
52
+ !args.user_id &&
53
+ !args.context) {
54
+ return undefined;
55
+ }
56
+ return compact({
57
+ webhook: args.openclaw_webhook_url
58
+ ? compact({
59
+ url: args.openclaw_webhook_url,
60
+ method: "POST",
61
+ headers: args.openclaw_webhook_authorization
62
+ ? {
63
+ Authorization: args.openclaw_webhook_authorization,
64
+ }
65
+ : undefined,
66
+ })
67
+ : undefined,
68
+ webhookPayload: compact({
69
+ conversation_id: args.conversation_id,
70
+ user_id: args.user_id,
71
+ context: args.context,
72
+ }),
73
+ });
74
+ }
75
+ function compact(values) {
76
+ return Object.fromEntries(Object.entries(values).filter(([, value]) => value !== undefined));
77
+ }
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "clawdcall-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for ClawdCall's agent-facing phone execution API.",
5
+ "type": "module",
6
+ "bin": {
7
+ "clawdcall-mcp": "dist/index.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "files": [
11
+ "dist",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "dev": "tsx src/index.ts",
18
+ "start": "node dist/index.js",
19
+ "typecheck": "tsc --noEmit",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "keywords": [
23
+ "clawdcall",
24
+ "mcp",
25
+ "model-context-protocol",
26
+ "telephony",
27
+ "phone",
28
+ "voice",
29
+ "ai-agents",
30
+ "openclaw",
31
+ "claude-code"
32
+ ],
33
+ "author": "ClawdCall",
34
+ "license": "MIT",
35
+ "homepage": "https://github.com/dialgoodian/clawdcall-mcp#readme",
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/dialgoodian/clawdcall-mcp.git"
39
+ },
40
+ "bugs": {
41
+ "url": "https://github.com/dialgoodian/clawdcall-mcp/issues"
42
+ },
43
+ "engines": {
44
+ "node": ">=18"
45
+ },
46
+ "dependencies": {
47
+ "@modelcontextprotocol/sdk": "^1.13.0",
48
+ "zod": "^3.25.0"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "^22.15.0",
52
+ "tsx": "^4.19.0",
53
+ "typescript": "^5.8.0"
54
+ }
55
+ }