@zyphr-dev/mcp-server 0.1.0 → 0.1.1
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/package.json +5 -6
- package/src/client.ts +0 -25
- package/src/config.test.ts +0 -64
- package/src/config.ts +0 -33
- package/src/index.ts +0 -24
- package/src/integration/quickstart/email.ts +0 -646
- package/src/integration/quickstart/inbox.ts +0 -222
- package/src/integration/quickstart/index.ts +0 -45
- package/src/integration/quickstart/push.ts +0 -216
- package/src/integration/quickstart/quickstart.test.ts +0 -108
- package/src/integration/quickstart/sms.ts +0 -205
- package/src/integration/quickstart/webhook.ts +0 -664
- package/src/integration/quickstart-types.ts +0 -31
- package/src/integration/sdk-snippets.test.ts +0 -63
- package/src/integration/sdk-snippets.ts +0 -248
- package/src/result.test.ts +0 -107
- package/src/result.ts +0 -65
- package/src/schemas.ts +0 -231
- package/src/server.ts +0 -26
- package/src/tools/index.ts +0 -7
- package/src/tools/integration.ts +0 -54
- package/src/tools/send.ts +0 -153
- package/src/tools/subscribers.ts +0 -126
- package/src/tools/templates.ts +0 -87
- package/src/tools/webhooks.ts +0 -82
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zyphr-dev/mcp-server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Model Context Protocol server for Zyphr — wraps the Zyphr API as MCP tools for AI clients",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.js",
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"bin": {
|
|
10
|
-
"zyphr-mcp": "
|
|
10
|
+
"zyphr-mcp": "dist/index.js"
|
|
11
11
|
},
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
"sideEffects": false,
|
|
19
19
|
"files": [
|
|
20
20
|
"dist",
|
|
21
|
-
"src",
|
|
22
21
|
"README.md"
|
|
23
22
|
],
|
|
24
23
|
"scripts": {
|
|
@@ -30,7 +29,7 @@
|
|
|
30
29
|
},
|
|
31
30
|
"dependencies": {
|
|
32
31
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
33
|
-
"@zyphr-dev/node-sdk": "
|
|
32
|
+
"@zyphr-dev/node-sdk": "0.1.19-dev.21d96db4",
|
|
34
33
|
"zod": "^3.23.0"
|
|
35
34
|
},
|
|
36
35
|
"devDependencies": {
|
|
@@ -53,10 +52,10 @@
|
|
|
53
52
|
"license": "MIT",
|
|
54
53
|
"repository": {
|
|
55
54
|
"type": "git",
|
|
56
|
-
"url": "https://github.com/arcraz/zyphr.git",
|
|
55
|
+
"url": "git+https://github.com/arcraz/zyphr.git",
|
|
57
56
|
"directory": "packages/mcp-server"
|
|
58
57
|
},
|
|
59
58
|
"engines": {
|
|
60
59
|
"node": ">=18.0.0"
|
|
61
60
|
}
|
|
62
|
-
}
|
|
61
|
+
}
|
package/src/client.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { Zyphr } from '@zyphr-dev/node-sdk';
|
|
2
|
-
|
|
3
|
-
const DEFAULT_BASE_URL = 'https://api.zyphr.dev/v1';
|
|
4
|
-
|
|
5
|
-
let cached: Zyphr | undefined;
|
|
6
|
-
|
|
7
|
-
export function getZyphrClient(): Zyphr {
|
|
8
|
-
if (cached) return cached;
|
|
9
|
-
|
|
10
|
-
const apiKey = process.env.ZYPHR_API_KEY;
|
|
11
|
-
if (!apiKey) {
|
|
12
|
-
process.stderr.write(
|
|
13
|
-
'[zyphr-mcp] ZYPHR_API_KEY is not set. Provide a zy_live_* or zy_test_* key via the `env` block of your MCP client config.\n',
|
|
14
|
-
);
|
|
15
|
-
process.exit(1);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const baseUrl = process.env.ZYPHR_BASE_URL || DEFAULT_BASE_URL;
|
|
19
|
-
cached = new Zyphr({ apiKey, baseUrl });
|
|
20
|
-
return cached;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function getBaseUrl(): string {
|
|
24
|
-
return process.env.ZYPHR_BASE_URL || DEFAULT_BASE_URL;
|
|
25
|
-
}
|
package/src/config.test.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, it } from 'vitest';
|
|
2
|
-
import { isToolEnabled, loadToolGuards } from './config.js';
|
|
3
|
-
|
|
4
|
-
const mutating = { name: 'send_email', mutates: true };
|
|
5
|
-
const reading = { name: 'list_templates', mutates: false };
|
|
6
|
-
|
|
7
|
-
const ENV_KEYS = ['ZYPHR_READ_ONLY', 'ZYPHR_ALLOWED_TOOLS'] as const;
|
|
8
|
-
|
|
9
|
-
function clearEnv(): void {
|
|
10
|
-
for (const k of ENV_KEYS) delete process.env[k];
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
describe('loadToolGuards + isToolEnabled', () => {
|
|
14
|
-
afterEach(clearEnv);
|
|
15
|
-
|
|
16
|
-
it('default: every tool enabled', () => {
|
|
17
|
-
const g = loadToolGuards();
|
|
18
|
-
expect(g.readOnly).toBe(false);
|
|
19
|
-
expect(g.allowedTools).toBeNull();
|
|
20
|
-
expect(isToolEnabled(mutating, g)).toBe(true);
|
|
21
|
-
expect(isToolEnabled(reading, g)).toBe(true);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('ZYPHR_READ_ONLY=true: mutating tools suppressed', () => {
|
|
25
|
-
process.env.ZYPHR_READ_ONLY = 'true';
|
|
26
|
-
const g = loadToolGuards();
|
|
27
|
-
expect(g.readOnly).toBe(true);
|
|
28
|
-
expect(isToolEnabled(mutating, g)).toBe(false);
|
|
29
|
-
expect(isToolEnabled(reading, g)).toBe(true);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('ZYPHR_READ_ONLY=1 also accepted', () => {
|
|
33
|
-
process.env.ZYPHR_READ_ONLY = '1';
|
|
34
|
-
const g = loadToolGuards();
|
|
35
|
-
expect(g.readOnly).toBe(true);
|
|
36
|
-
expect(isToolEnabled(mutating, g)).toBe(false);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('ZYPHR_ALLOWED_TOOLS limits the set', () => {
|
|
40
|
-
process.env.ZYPHR_ALLOWED_TOOLS = 'render_template, list_templates';
|
|
41
|
-
const g = loadToolGuards();
|
|
42
|
-
expect(g.allowedTools).not.toBeNull();
|
|
43
|
-
expect(isToolEnabled({ name: 'render_template', mutates: false }, g)).toBe(true);
|
|
44
|
-
expect(isToolEnabled({ name: 'list_templates', mutates: false }, g)).toBe(true);
|
|
45
|
-
expect(isToolEnabled({ name: 'send_email', mutates: true }, g)).toBe(false);
|
|
46
|
-
expect(isToolEnabled({ name: 'list_webhooks', mutates: false }, g)).toBe(false);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('whitelist overrides read-only (mutating tool can be explicitly allowed)', () => {
|
|
50
|
-
process.env.ZYPHR_READ_ONLY = 'true';
|
|
51
|
-
process.env.ZYPHR_ALLOWED_TOOLS = 'send_email';
|
|
52
|
-
const g = loadToolGuards();
|
|
53
|
-
expect(isToolEnabled({ name: 'send_email', mutates: true }, g)).toBe(true);
|
|
54
|
-
expect(isToolEnabled({ name: 'list_templates', mutates: false }, g)).toBe(false);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('empty ZYPHR_ALLOWED_TOOLS disables everything', () => {
|
|
58
|
-
process.env.ZYPHR_ALLOWED_TOOLS = '';
|
|
59
|
-
const g = loadToolGuards();
|
|
60
|
-
// empty string means no whitelist was set (null), so guards fall through
|
|
61
|
-
expect(g.allowedTools).toBeNull();
|
|
62
|
-
expect(isToolEnabled(reading, g)).toBe(true);
|
|
63
|
-
});
|
|
64
|
-
});
|
package/src/config.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
export interface ToolGuards {
|
|
2
|
-
readOnly: boolean;
|
|
3
|
-
allowedTools: Set<string> | null;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export function loadToolGuards(): ToolGuards {
|
|
7
|
-
const readOnly = process.env.ZYPHR_READ_ONLY === 'true' || process.env.ZYPHR_READ_ONLY === '1';
|
|
8
|
-
const raw = process.env.ZYPHR_ALLOWED_TOOLS;
|
|
9
|
-
const allowedTools = raw
|
|
10
|
-
? new Set(
|
|
11
|
-
raw
|
|
12
|
-
.split(',')
|
|
13
|
-
.map((s) => s.trim())
|
|
14
|
-
.filter(Boolean),
|
|
15
|
-
)
|
|
16
|
-
: null;
|
|
17
|
-
return { readOnly, allowedTools };
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface ToolDefinition {
|
|
21
|
-
name: string;
|
|
22
|
-
mutates: boolean;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function isToolEnabled(tool: ToolDefinition, guards: ToolGuards): boolean {
|
|
26
|
-
if (guards.allowedTools) {
|
|
27
|
-
return guards.allowedTools.has(tool.name);
|
|
28
|
-
}
|
|
29
|
-
if (guards.readOnly && tool.mutates) {
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
return true;
|
|
33
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
2
|
-
import { createServer } from './server.js';
|
|
3
|
-
import { getBaseUrl } from './client.js';
|
|
4
|
-
|
|
5
|
-
async function main(): Promise<void> {
|
|
6
|
-
// Touch the env early so misconfiguration fails fast with a clear message.
|
|
7
|
-
if (!process.env.ZYPHR_API_KEY) {
|
|
8
|
-
process.stderr.write(
|
|
9
|
-
'[zyphr-mcp] ZYPHR_API_KEY is not set. Provide a zy_live_* or zy_test_* key via the `env` block of your MCP client config.\n',
|
|
10
|
-
);
|
|
11
|
-
process.exit(1);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const server = createServer();
|
|
15
|
-
const transport = new StdioServerTransport();
|
|
16
|
-
await server.connect(transport);
|
|
17
|
-
|
|
18
|
-
process.stderr.write(`[zyphr-mcp] connected (base=${getBaseUrl()})\n`);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
main().catch((err) => {
|
|
22
|
-
process.stderr.write(`[zyphr-mcp] fatal: ${err instanceof Error ? err.stack ?? err.message : String(err)}\n`);
|
|
23
|
-
process.exit(1);
|
|
24
|
-
});
|