@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 CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@zyphr-dev/mcp-server",
3
- "version": "0.1.0",
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": "./dist/index.js"
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": "workspace:*",
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
- }
@@ -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
- });