@omnistreams/mcp-server 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/README.md +81 -0
- package/dist/client.d.ts +56 -0
- package/dist/client.js +129 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +22 -0
- package/dist/config.js +29 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/tools.d.ts +18 -0
- package/dist/tools.js +163 -0
- package/dist/tools.js.map +1 -0
- package/package.json +36 -0
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# @omnistreams/mcp-server
|
|
2
|
+
|
|
3
|
+
A [Model Context Protocol](https://modelcontextprotocol.io) server that bridges
|
|
4
|
+
the **OmniStream** REST API to MCP clients such as **Claude Desktop**, **Claude
|
|
5
|
+
Code** and **Cursor**. It lets an AI assistant read your inbox and send messages
|
|
6
|
+
on your behalf through natural language.
|
|
7
|
+
|
|
8
|
+
## Tools
|
|
9
|
+
|
|
10
|
+
| Tool | Description | Endpoint |
|
|
11
|
+
|---|---|---|
|
|
12
|
+
| `list_conversations` | List conversations (filter by status / assigned agent, paginated) | `GET /api/conversations` |
|
|
13
|
+
| `get_conversation` | Fetch one conversation by UUID | `GET /api/conversations/{id}` |
|
|
14
|
+
| `list_messages` | List messages in a conversation (cursor paginated) | `GET /api/conversations/{id}/messages` |
|
|
15
|
+
| `send_message` | Send an outbound message (text or rich content) | `POST /api/conversations/{id}/messages` |
|
|
16
|
+
| `list_contacts` | List / search contacts (by name, phone, email, tag) | `GET /api/contacts` |
|
|
17
|
+
| `search_messages` | Full-text search across messages | `GET /api/messages/search` |
|
|
18
|
+
| `list_templates` | List WhatsApp templates (filter by status / category / WABA) | `GET /api/wa-templates` |
|
|
19
|
+
|
|
20
|
+
All read tools are marked read-only. `send_message` is the only mutating tool.
|
|
21
|
+
|
|
22
|
+
## Setup
|
|
23
|
+
|
|
24
|
+
### 1. Create an API key
|
|
25
|
+
|
|
26
|
+
In OmniStream, go to **Developer → API Keys** and create a **REST** key
|
|
27
|
+
(requires the `developer.access` permission). Copy the key — it is shown once.
|
|
28
|
+
|
|
29
|
+
> **Tip:** lock the key to your server's IP using the key's **Allowed IPs**
|
|
30
|
+
> field so a leaked key cannot be used from anywhere else.
|
|
31
|
+
|
|
32
|
+
### 2. Configure the server
|
|
33
|
+
|
|
34
|
+
The server is configured entirely through environment variables:
|
|
35
|
+
|
|
36
|
+
| Variable | Required | Default | Description |
|
|
37
|
+
|---|---|---|---|
|
|
38
|
+
| `OMNISTREAM_API_KEY` | ✅ | — | REST API key (`os_..._...`) |
|
|
39
|
+
| `OMNISTREAM_BASE_URL` | | `http://localhost:3000` | API gateway base URL |
|
|
40
|
+
| `OMNISTREAM_TIMEOUT_MS` | | `30000` | Per-request timeout (ms) |
|
|
41
|
+
|
|
42
|
+
### 3. Add it to your MCP client
|
|
43
|
+
|
|
44
|
+
**Claude Desktop / Claude Code** (`claude_desktop_config.json` or `.mcp.json`):
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"mcpServers": {
|
|
49
|
+
"omnistream": {
|
|
50
|
+
"command": "npx",
|
|
51
|
+
"args": ["-y", "@omnistreams/mcp-server"],
|
|
52
|
+
"env": {
|
|
53
|
+
"OMNISTREAM_API_KEY": "os_xxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
|
54
|
+
"OMNISTREAM_BASE_URL": "https://your-omnistream-host"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Once configured, ask your assistant things like *"list my open WhatsApp
|
|
62
|
+
conversations"* or *"reply to conversation <id> with 'On my way!'"*.
|
|
63
|
+
|
|
64
|
+
## Local development
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npm install
|
|
68
|
+
npm run dev # run from source over stdio
|
|
69
|
+
npm run build # compile to dist/
|
|
70
|
+
npm test # unit tests (vitest)
|
|
71
|
+
npm run typecheck # type-check only
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Security notes
|
|
75
|
+
|
|
76
|
+
- The API key is sent as the `X-API-Key` header on every request; it is never
|
|
77
|
+
logged. Diagnostic output goes to **stderr** so it cannot corrupt the MCP
|
|
78
|
+
JSON-RPC stream on stdout.
|
|
79
|
+
- Requests inherit the RBAC of the key's owning agent — the server cannot do
|
|
80
|
+
anything the agent could not do in the UI.
|
|
81
|
+
- Combine with the API key **IP allow list** for defense in depth.
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal, dependency-free HTTP client for the OmniStream REST API.
|
|
3
|
+
*
|
|
4
|
+
* Authenticates with an API key via the `X-API-Key` header (see the OmniStream
|
|
5
|
+
* OpenAPI spec). The `fetch` implementation is injectable so the client can be
|
|
6
|
+
* unit-tested without a network.
|
|
7
|
+
*/
|
|
8
|
+
/** Query parameters; `undefined`/`null` values are omitted from the URL. */
|
|
9
|
+
export type Query = Record<string, string | number | boolean | undefined | null>;
|
|
10
|
+
/** Error thrown for non-2xx responses (and network/timeout failures). */
|
|
11
|
+
export declare class OmnistreamApiError extends Error {
|
|
12
|
+
/** HTTP status code, or 0 for network/timeout errors. */
|
|
13
|
+
readonly status: number;
|
|
14
|
+
/** Parsed error body, when the response carried one. */
|
|
15
|
+
readonly body?: unknown | undefined;
|
|
16
|
+
constructor(
|
|
17
|
+
/** HTTP status code, or 0 for network/timeout errors. */
|
|
18
|
+
status: number, message: string,
|
|
19
|
+
/** Parsed error body, when the response carried one. */
|
|
20
|
+
body?: unknown | undefined);
|
|
21
|
+
}
|
|
22
|
+
/** Construction options for {@link OmnistreamClient}. */
|
|
23
|
+
export interface OmnistreamClientOptions {
|
|
24
|
+
apiKey: string;
|
|
25
|
+
baseUrl: string;
|
|
26
|
+
requestTimeoutMs?: number;
|
|
27
|
+
/** Injectable fetch (defaults to the global). */
|
|
28
|
+
fetchImpl?: typeof fetch;
|
|
29
|
+
}
|
|
30
|
+
interface RequestOptions {
|
|
31
|
+
query?: Query;
|
|
32
|
+
body?: unknown;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Serialize a query object into a `?a=1&b=2` string, skipping nullish values.
|
|
36
|
+
* Returns an empty string when there is nothing to append.
|
|
37
|
+
*/
|
|
38
|
+
export declare function buildQueryString(query?: Query): string;
|
|
39
|
+
export declare class OmnistreamClient {
|
|
40
|
+
private readonly apiKey;
|
|
41
|
+
private readonly baseUrl;
|
|
42
|
+
private readonly requestTimeoutMs;
|
|
43
|
+
private readonly fetchImpl;
|
|
44
|
+
constructor(options: OmnistreamClientOptions);
|
|
45
|
+
/** GET `path` with optional query parameters. */
|
|
46
|
+
get<T>(path: string, query?: Query): Promise<T>;
|
|
47
|
+
/** POST `path` with a JSON body. */
|
|
48
|
+
post<T>(path: string, body?: unknown): Promise<T>;
|
|
49
|
+
/**
|
|
50
|
+
* Issue a request and parse the JSON response.
|
|
51
|
+
*
|
|
52
|
+
* @throws {@link OmnistreamApiError} on non-2xx status, timeout, or network failure.
|
|
53
|
+
*/
|
|
54
|
+
request<T>(method: string, path: string, options?: RequestOptions): Promise<T>;
|
|
55
|
+
}
|
|
56
|
+
export {};
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal, dependency-free HTTP client for the OmniStream REST API.
|
|
3
|
+
*
|
|
4
|
+
* Authenticates with an API key via the `X-API-Key` header (see the OmniStream
|
|
5
|
+
* OpenAPI spec). The `fetch` implementation is injectable so the client can be
|
|
6
|
+
* unit-tested without a network.
|
|
7
|
+
*/
|
|
8
|
+
/** Error thrown for non-2xx responses (and network/timeout failures). */
|
|
9
|
+
export class OmnistreamApiError extends Error {
|
|
10
|
+
status;
|
|
11
|
+
body;
|
|
12
|
+
constructor(
|
|
13
|
+
/** HTTP status code, or 0 for network/timeout errors. */
|
|
14
|
+
status, message,
|
|
15
|
+
/** Parsed error body, when the response carried one. */
|
|
16
|
+
body) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.status = status;
|
|
19
|
+
this.body = body;
|
|
20
|
+
this.name = "OmnistreamApiError";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Serialize a query object into a `?a=1&b=2` string, skipping nullish values.
|
|
25
|
+
* Returns an empty string when there is nothing to append.
|
|
26
|
+
*/
|
|
27
|
+
export function buildQueryString(query) {
|
|
28
|
+
if (!query)
|
|
29
|
+
return "";
|
|
30
|
+
const params = new URLSearchParams();
|
|
31
|
+
for (const [key, value] of Object.entries(query)) {
|
|
32
|
+
if (value === undefined || value === null)
|
|
33
|
+
continue;
|
|
34
|
+
params.append(key, String(value));
|
|
35
|
+
}
|
|
36
|
+
const qs = params.toString();
|
|
37
|
+
return qs ? `?${qs}` : "";
|
|
38
|
+
}
|
|
39
|
+
export class OmnistreamClient {
|
|
40
|
+
apiKey;
|
|
41
|
+
baseUrl;
|
|
42
|
+
requestTimeoutMs;
|
|
43
|
+
fetchImpl;
|
|
44
|
+
constructor(options) {
|
|
45
|
+
this.apiKey = options.apiKey;
|
|
46
|
+
this.baseUrl = options.baseUrl.replace(/\/+$/, "");
|
|
47
|
+
this.requestTimeoutMs = options.requestTimeoutMs ?? 30_000;
|
|
48
|
+
const f = options.fetchImpl ?? globalThis.fetch;
|
|
49
|
+
if (!f) {
|
|
50
|
+
throw new Error("No fetch implementation available (Node >= 18 required).");
|
|
51
|
+
}
|
|
52
|
+
// Bind so a passed-in global fetch keeps its expected `this`.
|
|
53
|
+
this.fetchImpl = f.bind(globalThis);
|
|
54
|
+
}
|
|
55
|
+
/** GET `path` with optional query parameters. */
|
|
56
|
+
get(path, query) {
|
|
57
|
+
return this.request("GET", path, { query });
|
|
58
|
+
}
|
|
59
|
+
/** POST `path` with a JSON body. */
|
|
60
|
+
post(path, body) {
|
|
61
|
+
return this.request("POST", path, { body });
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Issue a request and parse the JSON response.
|
|
65
|
+
*
|
|
66
|
+
* @throws {@link OmnistreamApiError} on non-2xx status, timeout, or network failure.
|
|
67
|
+
*/
|
|
68
|
+
async request(method, path, options = {}) {
|
|
69
|
+
const url = `${this.baseUrl}${path}${buildQueryString(options.query)}`;
|
|
70
|
+
const headers = { "X-API-Key": this.apiKey };
|
|
71
|
+
const hasBody = options.body !== undefined;
|
|
72
|
+
if (hasBody)
|
|
73
|
+
headers["Content-Type"] = "application/json";
|
|
74
|
+
const controller = new AbortController();
|
|
75
|
+
const timer = setTimeout(() => controller.abort(), this.requestTimeoutMs);
|
|
76
|
+
let res;
|
|
77
|
+
try {
|
|
78
|
+
res = await this.fetchImpl(url, {
|
|
79
|
+
method,
|
|
80
|
+
headers,
|
|
81
|
+
body: hasBody ? JSON.stringify(options.body) : undefined,
|
|
82
|
+
signal: controller.signal,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
const reason = err instanceof Error && err.name === "AbortError"
|
|
87
|
+
? `Request timed out after ${this.requestTimeoutMs}ms`
|
|
88
|
+
: `Network error: ${err instanceof Error ? err.message : String(err)}`;
|
|
89
|
+
throw new OmnistreamApiError(0, reason);
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
clearTimeout(timer);
|
|
93
|
+
}
|
|
94
|
+
const text = await res.text();
|
|
95
|
+
let parsed;
|
|
96
|
+
try {
|
|
97
|
+
parsed = text ? JSON.parse(text) : undefined;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
parsed = text;
|
|
101
|
+
}
|
|
102
|
+
if (!res.ok) {
|
|
103
|
+
throw new OmnistreamApiError(res.status, extractErrorMessage(parsed, res.status), parsed);
|
|
104
|
+
}
|
|
105
|
+
return parsed;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Pull a human-readable message out of an OmniStream error envelope
|
|
110
|
+
* (`{ error: { message } }`), falling back to a plain string body or the
|
|
111
|
+
* status code.
|
|
112
|
+
*/
|
|
113
|
+
function extractErrorMessage(body, status) {
|
|
114
|
+
if (typeof body === "string" && body.trim())
|
|
115
|
+
return body.trim();
|
|
116
|
+
if (body && typeof body === "object") {
|
|
117
|
+
const err = body.error;
|
|
118
|
+
if (typeof err === "string")
|
|
119
|
+
return err;
|
|
120
|
+
if (err && typeof err === "object" && typeof err.message === "string") {
|
|
121
|
+
return err.message;
|
|
122
|
+
}
|
|
123
|
+
const msg = body.message;
|
|
124
|
+
if (typeof msg === "string")
|
|
125
|
+
return msg;
|
|
126
|
+
}
|
|
127
|
+
return `HTTP ${status}`;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration loading for the OmniStream MCP server.
|
|
3
|
+
*
|
|
4
|
+
* All settings come from environment variables so the server can be launched by
|
|
5
|
+
* any MCP client (Claude Desktop, Cursor, …) via a simple `env` block.
|
|
6
|
+
*/
|
|
7
|
+
/** Resolved, validated configuration for the MCP server. */
|
|
8
|
+
export interface OmnistreamMcpConfig {
|
|
9
|
+
/** REST API key sent as the `X-API-Key` header on every request. */
|
|
10
|
+
apiKey: string;
|
|
11
|
+
/** Base URL of the OmniStream API gateway, without a trailing slash. */
|
|
12
|
+
baseUrl: string;
|
|
13
|
+
/** Per-request timeout in milliseconds. */
|
|
14
|
+
requestTimeoutMs: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Build a validated {@link OmnistreamMcpConfig} from environment variables.
|
|
18
|
+
*
|
|
19
|
+
* @param env - environment to read from (defaults to `process.env`; injectable for tests).
|
|
20
|
+
* @throws Error when `OMNISTREAM_API_KEY` is missing or the timeout is not a positive integer.
|
|
21
|
+
*/
|
|
22
|
+
export declare function loadConfig(env?: NodeJS.ProcessEnv): OmnistreamMcpConfig;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration loading for the OmniStream MCP server.
|
|
3
|
+
*
|
|
4
|
+
* All settings come from environment variables so the server can be launched by
|
|
5
|
+
* any MCP client (Claude Desktop, Cursor, …) via a simple `env` block.
|
|
6
|
+
*/
|
|
7
|
+
const DEFAULT_BASE_URL = "http://localhost:3000";
|
|
8
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
9
|
+
/**
|
|
10
|
+
* Build a validated {@link OmnistreamMcpConfig} from environment variables.
|
|
11
|
+
*
|
|
12
|
+
* @param env - environment to read from (defaults to `process.env`; injectable for tests).
|
|
13
|
+
* @throws Error when `OMNISTREAM_API_KEY` is missing or the timeout is not a positive integer.
|
|
14
|
+
*/
|
|
15
|
+
export function loadConfig(env = process.env) {
|
|
16
|
+
const apiKey = env.OMNISTREAM_API_KEY?.trim();
|
|
17
|
+
if (!apiKey) {
|
|
18
|
+
throw new Error("OMNISTREAM_API_KEY is required. Create a REST API key in OmniStream → Developer → API Keys.");
|
|
19
|
+
}
|
|
20
|
+
// Strip any trailing slashes so `baseUrl + "/api/..."` never doubles up.
|
|
21
|
+
const baseUrl = (env.OMNISTREAM_BASE_URL?.trim() || DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
22
|
+
const timeoutRaw = env.OMNISTREAM_TIMEOUT_MS?.trim();
|
|
23
|
+
const requestTimeoutMs = timeoutRaw ? Number.parseInt(timeoutRaw, 10) : DEFAULT_TIMEOUT_MS;
|
|
24
|
+
if (!Number.isFinite(requestTimeoutMs) || requestTimeoutMs <= 0) {
|
|
25
|
+
throw new Error(`OMNISTREAM_TIMEOUT_MS must be a positive integer (got "${timeoutRaw}").`);
|
|
26
|
+
}
|
|
27
|
+
return { apiKey, baseUrl, requestTimeoutMs };
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AACjD,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAElC;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7D,MAAM,MAAM,GAAG,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE,CAAC;IAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,6FAA6F,CAC9F,CAAC;IACJ,CAAC;IAED,yEAAyE;IACzE,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,mBAAmB,EAAE,IAAI,EAAE,IAAI,gBAAgB,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAE1F,MAAM,UAAU,GAAG,GAAG,CAAC,qBAAqB,EAAE,IAAI,EAAE,CAAC;IACrD,MAAM,gBAAgB,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC;IAC3F,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,gBAAgB,IAAI,CAAC,EAAE,CAAC;QAChE,MAAM,IAAI,KAAK,CACb,0DAA0D,UAAU,KAAK,CAC1E,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC;AAC/C,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* OmniStream MCP server entry point.
|
|
4
|
+
*
|
|
5
|
+
* Reads configuration from the environment, builds an authenticated REST
|
|
6
|
+
* client, registers the OmniStream tools and serves them over stdio — the
|
|
7
|
+
* transport used by Claude Desktop, Cursor and most MCP clients.
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* OmniStream MCP server entry point.
|
|
4
|
+
*
|
|
5
|
+
* Reads configuration from the environment, builds an authenticated REST
|
|
6
|
+
* client, registers the OmniStream tools and serves them over stdio — the
|
|
7
|
+
* transport used by Claude Desktop, Cursor and most MCP clients.
|
|
8
|
+
*/
|
|
9
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
10
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
11
|
+
import { loadConfig } from "./config.js";
|
|
12
|
+
import { OmnistreamClient } from "./client.js";
|
|
13
|
+
import { registerTools } from "./tools.js";
|
|
14
|
+
/** Package version, kept in sync with package.json. */
|
|
15
|
+
const VERSION = "0.1.0";
|
|
16
|
+
async function main() {
|
|
17
|
+
const config = loadConfig();
|
|
18
|
+
const client = new OmnistreamClient({
|
|
19
|
+
apiKey: config.apiKey,
|
|
20
|
+
baseUrl: config.baseUrl,
|
|
21
|
+
requestTimeoutMs: config.requestTimeoutMs,
|
|
22
|
+
});
|
|
23
|
+
const server = new McpServer({ name: "omnistream", version: VERSION });
|
|
24
|
+
registerTools(server, client);
|
|
25
|
+
const transport = new StdioServerTransport();
|
|
26
|
+
await server.connect(transport);
|
|
27
|
+
// Log to stderr — stdout is reserved for the MCP JSON-RPC stream.
|
|
28
|
+
console.error(`OmniStream MCP server v${VERSION} running (base URL: ${config.baseUrl})`);
|
|
29
|
+
}
|
|
30
|
+
main().catch((err) => {
|
|
31
|
+
console.error(`Fatal: ${err instanceof Error ? err.message : String(err)}`);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
});
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,uDAAuD;AACvD,MAAM,OAAO,GAAG,OAAO,CAAC;AAExB,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAE5B,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC;QAClC,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;KAC1C,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACvE,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,kEAAkE;IAClE,OAAO,CAAC,KAAK,CAAC,0BAA0B,OAAO,uBAAuB,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC;AAC3F,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/tools.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool definitions for OmniStream.
|
|
3
|
+
*
|
|
4
|
+
* Each tool maps to one OmniStream REST endpoint. Results are returned as
|
|
5
|
+
* pretty-printed JSON text; failures surface the API error message with
|
|
6
|
+
* `isError: true` so the model can react instead of the call throwing.
|
|
7
|
+
*/
|
|
8
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
9
|
+
import { type OmnistreamClient } from "./client.js";
|
|
10
|
+
/**
|
|
11
|
+
* Register every OmniStream tool on the given MCP server.
|
|
12
|
+
*
|
|
13
|
+
* @param server - the MCP server instance.
|
|
14
|
+
* @param client - an authenticated OmniStream REST client.
|
|
15
|
+
*/
|
|
16
|
+
export declare function registerTools(server: McpServer, client: OmnistreamClient): void;
|
|
17
|
+
/** Names of all registered tools — exported for tests and documentation. */
|
|
18
|
+
export declare const TOOL_NAMES: readonly ["list_conversations", "get_conversation", "list_messages", "send_message", "list_contacts", "search_messages", "list_templates"];
|
package/dist/tools.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool definitions for OmniStream.
|
|
3
|
+
*
|
|
4
|
+
* Each tool maps to one OmniStream REST endpoint. Results are returned as
|
|
5
|
+
* pretty-printed JSON text; failures surface the API error message with
|
|
6
|
+
* `isError: true` so the model can react instead of the call throwing.
|
|
7
|
+
*/
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
import { OmnistreamApiError } from "./client.js";
|
|
10
|
+
/** Wrap a successful value as a JSON text result. */
|
|
11
|
+
function jsonResult(data) {
|
|
12
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
13
|
+
}
|
|
14
|
+
/** Wrap an error as an `isError` text result (never throws out of a tool). */
|
|
15
|
+
function errorResult(err) {
|
|
16
|
+
const message = err instanceof OmnistreamApiError
|
|
17
|
+
? `OmniStream API error (${err.status}): ${err.message}`
|
|
18
|
+
: err instanceof Error
|
|
19
|
+
? err.message
|
|
20
|
+
: String(err);
|
|
21
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
22
|
+
}
|
|
23
|
+
/** Run an async producer, converting success/failure into a tool result. */
|
|
24
|
+
async function run(fn) {
|
|
25
|
+
try {
|
|
26
|
+
return jsonResult(await fn());
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
return errorResult(err);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const READ_ONLY = { readOnlyHint: true };
|
|
33
|
+
/**
|
|
34
|
+
* Register every OmniStream tool on the given MCP server.
|
|
35
|
+
*
|
|
36
|
+
* @param server - the MCP server instance.
|
|
37
|
+
* @param client - an authenticated OmniStream REST client.
|
|
38
|
+
*/
|
|
39
|
+
export function registerTools(server, client) {
|
|
40
|
+
server.registerTool("list_conversations", {
|
|
41
|
+
title: "List conversations",
|
|
42
|
+
description: "List conversations in the inbox. Supports filtering by status and assigned agent, with pagination.",
|
|
43
|
+
inputSchema: {
|
|
44
|
+
status: z
|
|
45
|
+
.enum(["open", "pending", "resolved", "expired"])
|
|
46
|
+
.optional()
|
|
47
|
+
.describe("Filter by conversation status."),
|
|
48
|
+
assigned_agent_id: z.string().optional().describe("Filter by assigned agent UUID."),
|
|
49
|
+
page: z.number().int().min(1).optional().describe("1-based page number (default 1)."),
|
|
50
|
+
per_page: z
|
|
51
|
+
.number()
|
|
52
|
+
.int()
|
|
53
|
+
.min(1)
|
|
54
|
+
.max(100)
|
|
55
|
+
.optional()
|
|
56
|
+
.describe("Items per page (1-100, default 20)."),
|
|
57
|
+
},
|
|
58
|
+
annotations: READ_ONLY,
|
|
59
|
+
}, async (args) => run(() => client.get("/api/conversations", args)));
|
|
60
|
+
server.registerTool("get_conversation", {
|
|
61
|
+
title: "Get a conversation",
|
|
62
|
+
description: "Fetch a single conversation (with its contact) by UUID.",
|
|
63
|
+
inputSchema: {
|
|
64
|
+
conversation_id: z.string().describe("Conversation UUID."),
|
|
65
|
+
},
|
|
66
|
+
annotations: READ_ONLY,
|
|
67
|
+
}, async ({ conversation_id }) => run(() => client.get(`/api/conversations/${encodeURIComponent(conversation_id)}`)));
|
|
68
|
+
server.registerTool("list_messages", {
|
|
69
|
+
title: "List messages in a conversation",
|
|
70
|
+
description: "List messages in a conversation, newest first, using cursor pagination.",
|
|
71
|
+
inputSchema: {
|
|
72
|
+
conversation_id: z.string().describe("Conversation UUID."),
|
|
73
|
+
cursor: z.string().optional().describe("MongoDB ObjectId hex cursor from a previous page."),
|
|
74
|
+
limit: z
|
|
75
|
+
.number()
|
|
76
|
+
.int()
|
|
77
|
+
.min(1)
|
|
78
|
+
.max(100)
|
|
79
|
+
.optional()
|
|
80
|
+
.describe("Max messages to return (1-100, default 50)."),
|
|
81
|
+
},
|
|
82
|
+
annotations: READ_ONLY,
|
|
83
|
+
}, async ({ conversation_id, cursor, limit }) => run(() => client.get(`/api/conversations/${encodeURIComponent(conversation_id)}/messages`, {
|
|
84
|
+
cursor,
|
|
85
|
+
limit,
|
|
86
|
+
})));
|
|
87
|
+
server.registerTool("send_message", {
|
|
88
|
+
title: "Send a message",
|
|
89
|
+
description: "Send an outbound message in a conversation. For a plain text message pass `text`; for richer types (image, etc.) pass a raw `content` object. The message is queued and delivered via WhatsApp/Instagram/Email by the sender service.",
|
|
90
|
+
inputSchema: {
|
|
91
|
+
conversation_id: z.string().describe("Conversation UUID to send into."),
|
|
92
|
+
type: z
|
|
93
|
+
.string()
|
|
94
|
+
.default("text")
|
|
95
|
+
.describe("Message type: 'text', 'image', 'document', etc. (default 'text')."),
|
|
96
|
+
text: z.string().optional().describe("Text body — used when `type` is 'text'."),
|
|
97
|
+
content: z
|
|
98
|
+
.record(z.any())
|
|
99
|
+
.optional()
|
|
100
|
+
.describe('Raw content object (e.g. {"url":"...","caption":"..."}). Overrides `text` when provided.'),
|
|
101
|
+
},
|
|
102
|
+
annotations: { readOnlyHint: false },
|
|
103
|
+
}, async ({ conversation_id, type, text, content }) => run(() => {
|
|
104
|
+
const resolvedContent = content ?? (text !== undefined ? { text } : undefined);
|
|
105
|
+
if (resolvedContent === undefined) {
|
|
106
|
+
throw new Error("Provide either `text` (for a text message) or a `content` object.");
|
|
107
|
+
}
|
|
108
|
+
return client.post(`/api/conversations/${encodeURIComponent(conversation_id)}/messages`, { type, content: resolvedContent });
|
|
109
|
+
}));
|
|
110
|
+
server.registerTool("list_contacts", {
|
|
111
|
+
title: "List/search contacts",
|
|
112
|
+
description: "List contacts, optionally searching by name/phone/email and filtering by tag.",
|
|
113
|
+
inputSchema: {
|
|
114
|
+
search: z.string().optional().describe("Search by name, phone, or email (case-insensitive)."),
|
|
115
|
+
tag: z.string().optional().describe("Filter by a single tag."),
|
|
116
|
+
page: z.number().int().min(1).optional().describe("1-based page number (default 1)."),
|
|
117
|
+
per_page: z
|
|
118
|
+
.number()
|
|
119
|
+
.int()
|
|
120
|
+
.min(1)
|
|
121
|
+
.max(100)
|
|
122
|
+
.optional()
|
|
123
|
+
.describe("Items per page (1-100, default 20)."),
|
|
124
|
+
},
|
|
125
|
+
annotations: READ_ONLY,
|
|
126
|
+
}, async (args) => run(() => client.get("/api/contacts", args)));
|
|
127
|
+
server.registerTool("search_messages", {
|
|
128
|
+
title: "Search messages",
|
|
129
|
+
description: "Full-text search of message content across all conversations.",
|
|
130
|
+
inputSchema: {
|
|
131
|
+
q: z.string().describe("Search query (message text)."),
|
|
132
|
+
limit: z.number().int().min(1).max(100).optional().describe("Max results (default 20)."),
|
|
133
|
+
},
|
|
134
|
+
annotations: READ_ONLY,
|
|
135
|
+
}, async ({ q, limit }) => run(() => client.get("/api/messages/search", { q, limit })));
|
|
136
|
+
server.registerTool("list_templates", {
|
|
137
|
+
title: "List WhatsApp templates",
|
|
138
|
+
description: "List WhatsApp message templates, optionally filtered by status, category or WABA.",
|
|
139
|
+
inputSchema: {
|
|
140
|
+
status: z
|
|
141
|
+
.enum(["APPROVED", "PENDING", "REJECTED", "PAUSED", "DISABLED"])
|
|
142
|
+
.optional()
|
|
143
|
+
.describe("Filter by template review status."),
|
|
144
|
+
category: z
|
|
145
|
+
.enum(["MARKETING", "UTILITY", "AUTHENTICATION"])
|
|
146
|
+
.optional()
|
|
147
|
+
.describe("Filter by template category."),
|
|
148
|
+
waba_id: z.string().optional().describe("Filter by WhatsApp Business Account ID."),
|
|
149
|
+
},
|
|
150
|
+
annotations: READ_ONLY,
|
|
151
|
+
}, async (args) => run(() => client.get("/api/wa-templates", args)));
|
|
152
|
+
}
|
|
153
|
+
/** Names of all registered tools — exported for tests and documentation. */
|
|
154
|
+
export const TOOL_NAMES = [
|
|
155
|
+
"list_conversations",
|
|
156
|
+
"get_conversation",
|
|
157
|
+
"list_messages",
|
|
158
|
+
"send_message",
|
|
159
|
+
"list_contacts",
|
|
160
|
+
"search_messages",
|
|
161
|
+
"list_templates",
|
|
162
|
+
];
|
|
163
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@omnistreams/mcp-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Model Context Protocol (MCP) server for OmniStream — lets Claude, Cursor and other MCP clients send messages and manage conversations, contacts and templates via the OmniStream REST API.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"omnistreams-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=18"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc -p tsconfig.json",
|
|
19
|
+
"prepublishOnly": "npm run build",
|
|
20
|
+
"dev": "tsx src/index.ts",
|
|
21
|
+
"start": "node dist/index.js",
|
|
22
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"test:watch": "vitest"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
28
|
+
"zod": "^3.25.0"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^24.0.0",
|
|
32
|
+
"tsx": "^4.19.0",
|
|
33
|
+
"typescript": "^5.6.0",
|
|
34
|
+
"vitest": "^3.2.0"
|
|
35
|
+
}
|
|
36
|
+
}
|