@kywi-software/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.
Files changed (119) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +77 -0
  3. package/dist/__tests__/auto-detect.test.d.ts +2 -0
  4. package/dist/__tests__/auto-detect.test.d.ts.map +1 -0
  5. package/dist/__tests__/auto-detect.test.js +134 -0
  6. package/dist/__tests__/auto-detect.test.js.map +1 -0
  7. package/dist/__tests__/config.test.d.ts +2 -0
  8. package/dist/__tests__/config.test.d.ts.map +1 -0
  9. package/dist/__tests__/config.test.js +72 -0
  10. package/dist/__tests__/config.test.js.map +1 -0
  11. package/dist/__tests__/developer-mutation.test.d.ts +2 -0
  12. package/dist/__tests__/developer-mutation.test.d.ts.map +1 -0
  13. package/dist/__tests__/developer-mutation.test.js +511 -0
  14. package/dist/__tests__/developer-mutation.test.js.map +1 -0
  15. package/dist/__tests__/developer-read-only.test.d.ts +2 -0
  16. package/dist/__tests__/developer-read-only.test.d.ts.map +1 -0
  17. package/dist/__tests__/developer-read-only.test.js +192 -0
  18. package/dist/__tests__/developer-read-only.test.js.map +1 -0
  19. package/dist/__tests__/site-content-tools.test.d.ts +2 -0
  20. package/dist/__tests__/site-content-tools.test.d.ts.map +1 -0
  21. package/dist/__tests__/site-content-tools.test.js +446 -0
  22. package/dist/__tests__/site-content-tools.test.js.map +1 -0
  23. package/dist/__tests__/site-layout-tools.test.d.ts +2 -0
  24. package/dist/__tests__/site-layout-tools.test.d.ts.map +1 -0
  25. package/dist/__tests__/site-layout-tools.test.js +316 -0
  26. package/dist/__tests__/site-layout-tools.test.js.map +1 -0
  27. package/dist/__tests__/site-other-tools.test.d.ts +2 -0
  28. package/dist/__tests__/site-other-tools.test.d.ts.map +1 -0
  29. package/dist/__tests__/site-other-tools.test.js +318 -0
  30. package/dist/__tests__/site-other-tools.test.js.map +1 -0
  31. package/dist/config.d.ts +31 -0
  32. package/dist/config.d.ts.map +1 -0
  33. package/dist/config.js +4 -0
  34. package/dist/config.js.map +1 -0
  35. package/dist/developer/auto-detect.d.ts +17 -0
  36. package/dist/developer/auto-detect.d.ts.map +1 -0
  37. package/dist/developer/auto-detect.js +54 -0
  38. package/dist/developer/auto-detect.js.map +1 -0
  39. package/dist/developer/cli.d.ts +3 -0
  40. package/dist/developer/cli.d.ts.map +1 -0
  41. package/dist/developer/cli.js +14 -0
  42. package/dist/developer/cli.js.map +1 -0
  43. package/dist/developer/index.d.ts +4 -0
  44. package/dist/developer/index.d.ts.map +1 -0
  45. package/dist/developer/index.js +9 -0
  46. package/dist/developer/index.js.map +1 -0
  47. package/dist/developer/server.d.ts +4 -0
  48. package/dist/developer/server.d.ts.map +1 -0
  49. package/dist/developer/server.js +29 -0
  50. package/dist/developer/server.js.map +1 -0
  51. package/dist/developer/tools/api-keys.d.ts +48 -0
  52. package/dist/developer/tools/api-keys.d.ts.map +1 -0
  53. package/dist/developer/tools/api-keys.js +51 -0
  54. package/dist/developer/tools/api-keys.js.map +1 -0
  55. package/dist/developer/tools/config-mutation.d.ts +139 -0
  56. package/dist/developer/tools/config-mutation.d.ts.map +1 -0
  57. package/dist/developer/tools/config-mutation.js +277 -0
  58. package/dist/developer/tools/config-mutation.js.map +1 -0
  59. package/dist/developer/tools/content-type-tools.d.ts +32 -0
  60. package/dist/developer/tools/content-type-tools.d.ts.map +1 -0
  61. package/dist/developer/tools/content-type-tools.js +92 -0
  62. package/dist/developer/tools/content-type-tools.js.map +1 -0
  63. package/dist/developer/tools/read-only.d.ts +86 -0
  64. package/dist/developer/tools/read-only.d.ts.map +1 -0
  65. package/dist/developer/tools/read-only.js +235 -0
  66. package/dist/developer/tools/read-only.js.map +1 -0
  67. package/dist/developer/tools/scaffolding.d.ts +67 -0
  68. package/dist/developer/tools/scaffolding.d.ts.map +1 -0
  69. package/dist/developer/tools/scaffolding.js +207 -0
  70. package/dist/developer/tools/scaffolding.js.map +1 -0
  71. package/dist/index.d.ts +7 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +6 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/shared.d.ts +15 -0
  76. package/dist/shared.d.ts.map +1 -0
  77. package/dist/shared.js +7 -0
  78. package/dist/shared.js.map +1 -0
  79. package/dist/site/cli.d.ts +3 -0
  80. package/dist/site/cli.d.ts.map +1 -0
  81. package/dist/site/cli.js +12 -0
  82. package/dist/site/cli.js.map +1 -0
  83. package/dist/site/index.d.ts +4 -0
  84. package/dist/site/index.d.ts.map +1 -0
  85. package/dist/site/index.js +9 -0
  86. package/dist/site/index.js.map +1 -0
  87. package/dist/site/server.d.ts +10 -0
  88. package/dist/site/server.d.ts.map +1 -0
  89. package/dist/site/server.js +73 -0
  90. package/dist/site/server.js.map +1 -0
  91. package/dist/site/tools/content.d.ts +250 -0
  92. package/dist/site/tools/content.d.ts.map +1 -0
  93. package/dist/site/tools/content.js +329 -0
  94. package/dist/site/tools/content.js.map +1 -0
  95. package/dist/site/tools/feeds.d.ts +62 -0
  96. package/dist/site/tools/feeds.d.ts.map +1 -0
  97. package/dist/site/tools/feeds.js +97 -0
  98. package/dist/site/tools/feeds.js.map +1 -0
  99. package/dist/site/tools/layout.d.ts +163 -0
  100. package/dist/site/tools/layout.d.ts.map +1 -0
  101. package/dist/site/tools/layout.js +226 -0
  102. package/dist/site/tools/layout.js.map +1 -0
  103. package/dist/site/tools/media.d.ts +38 -0
  104. package/dist/site/tools/media.d.ts.map +1 -0
  105. package/dist/site/tools/media.js +52 -0
  106. package/dist/site/tools/media.js.map +1 -0
  107. package/dist/site/tools/search.d.ts +40 -0
  108. package/dist/site/tools/search.d.ts.map +1 -0
  109. package/dist/site/tools/search.js +60 -0
  110. package/dist/site/tools/search.js.map +1 -0
  111. package/dist/site/tools/users.d.ts +60 -0
  112. package/dist/site/tools/users.d.ts.map +1 -0
  113. package/dist/site/tools/users.js +71 -0
  114. package/dist/site/tools/users.js.map +1 -0
  115. package/dist/site/tools/webhooks.d.ts +34 -0
  116. package/dist/site/tools/webhooks.d.ts.map +1 -0
  117. package/dist/site/tools/webhooks.js +44 -0
  118. package/dist/site/tools/webhooks.js.map +1 -0
  119. package/package.json +61 -0
package/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # @kywi-software/mcp
2
+
3
+ Two [Model Context Protocol](https://modelcontextprotocol.io) servers for
4
+ Kywi CMS, so an AI agent can author content or scaffold a project over
5
+ stdio:
6
+
7
+ - **`kywi-mcp-site`** — content-authoring tools (content, layout, media,
8
+ search, users, feeds, webhooks) against a *running* Kywi site's REST API.
9
+ Built on `@kywi-software/sdk`.
10
+ - **`kywi-mcp-dev`** — project scaffolding and config tools: read/mutate a
11
+ local `kywi.config.ts` (content types, sites, themes), or drive the same
12
+ operations over the REST API.
13
+
14
+ See the [root README](https://github.com/kywi-software/kywi#readme) for how
15
+ this fits into the rest of Kywi.
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ npm install -g @kywi-software/mcp
21
+ # or: npx @kywi-software/mcp
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ Both binaries speak MCP over stdio — wire them into an MCP-capable client
27
+ (e.g. Claude Code, Claude Desktop) via its server config.
28
+
29
+ ### `kywi-mcp-site`
30
+
31
+ ```json
32
+ {
33
+ "mcpServers": {
34
+ "kywi-site": {
35
+ "command": "kywi-mcp-site",
36
+ "env": {
37
+ "KYWI_API_URL": "https://your-site.example.com/api/v1",
38
+ "KYWI_MCP_API_KEY": "kywi_xxxxxxxx"
39
+ }
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ `KYWI_API_URL` defaults to `http://localhost:3000/api/v1` if unset.
46
+
47
+ ### `kywi-mcp-dev`
48
+
49
+ ```json
50
+ {
51
+ "mcpServers": {
52
+ "kywi-dev": {
53
+ "command": "kywi-mcp-dev",
54
+ "env": {
55
+ "KYWI_CONFIG_PATH": "/path/to/project/kywi.config.ts"
56
+ }
57
+ }
58
+ }
59
+ }
60
+ ```
61
+
62
+ Env vars: `KYWI_CONFIG_PATH` (filesystem mode — read/mutate `kywi.config.ts`
63
+ directly), `KYWI_API_URL` / `KYWI_MCP_DEV_KEY` (API mode), and
64
+ `KYWI_MCP_MODE` (`filesystem` | `api` | `auto`, default `auto` — picks
65
+ filesystem mode when `configPath` is writable, otherwise API mode).
66
+
67
+ ## What's in the package
68
+
69
+ - `.` — shared config types (`defineMcpConfig`, `McpConfig`).
70
+ - `./site` — `createSiteMcpServer`, the site server's tool implementations
71
+ (`packages/mcp/src/site/tools/*.ts`).
72
+ - `./developer` — `createDeveloperMcpServer`, the developer server's tool
73
+ implementations (`packages/mcp/src/developer/tools/*.ts`), including
74
+ filesystem config mutation and content-type scaffolding.
75
+
76
+ `packages/mcp/src/config.ts` and the `tools/` directories are the source of
77
+ truth for exact tool names and schemas.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=auto-detect.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-detect.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/auto-detect.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,134 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { detectMode, detectSplitMode } from '../developer/auto-detect.js';
3
+ vi.mock('node:fs', () => ({
4
+ accessSync: vi.fn(),
5
+ constants: { W_OK: 2 },
6
+ }));
7
+ import { accessSync } from 'node:fs';
8
+ const mockedAccessSync = vi.mocked(accessSync);
9
+ beforeEach(() => {
10
+ vi.clearAllMocks();
11
+ });
12
+ describe('detectMode', () => {
13
+ it('returns filesystem when configPath is writable', () => {
14
+ mockedAccessSync.mockImplementation(() => undefined);
15
+ const config = {
16
+ enabled: true,
17
+ mode: 'auto',
18
+ configPath: '/project/kywi.config.ts',
19
+ };
20
+ expect(detectMode(config)).toBe('filesystem');
21
+ });
22
+ it('returns api when configPath not writable but baseUrl + apiKey present', () => {
23
+ mockedAccessSync.mockImplementation(() => {
24
+ throw new Error('EACCES');
25
+ });
26
+ const config = {
27
+ enabled: true,
28
+ mode: 'auto',
29
+ configPath: '/project/kywi.config.ts',
30
+ baseUrl: 'http://localhost:3000/api/v1',
31
+ apiKey: 'test-key',
32
+ };
33
+ expect(detectMode(config)).toBe('api');
34
+ });
35
+ it('returns api when no configPath but baseUrl + apiKey present', () => {
36
+ const config = {
37
+ enabled: true,
38
+ mode: 'auto',
39
+ baseUrl: 'http://localhost:3000/api/v1',
40
+ apiKey: 'test-key',
41
+ };
42
+ expect(detectMode(config)).toBe('api');
43
+ });
44
+ it('throws when neither config file nor API credentials available', () => {
45
+ const config = {
46
+ enabled: true,
47
+ mode: 'auto',
48
+ };
49
+ expect(() => detectMode(config)).toThrow('Cannot detect MCP mode');
50
+ });
51
+ it('throws when configPath not writable and no API credentials', () => {
52
+ mockedAccessSync.mockImplementation(() => {
53
+ throw new Error('EACCES');
54
+ });
55
+ const config = {
56
+ enabled: true,
57
+ mode: 'auto',
58
+ configPath: '/project/kywi.config.ts',
59
+ };
60
+ expect(() => detectMode(config)).toThrow('Cannot detect MCP mode');
61
+ });
62
+ it('returns explicit filesystem mode without checking', () => {
63
+ const config = {
64
+ enabled: true,
65
+ mode: 'filesystem',
66
+ configPath: '/project/kywi.config.ts',
67
+ };
68
+ expect(detectMode(config)).toBe('filesystem');
69
+ expect(mockedAccessSync).not.toHaveBeenCalled();
70
+ });
71
+ it('returns explicit api mode without checking', () => {
72
+ const config = {
73
+ enabled: true,
74
+ mode: 'api',
75
+ baseUrl: 'http://localhost:3000/api/v1',
76
+ apiKey: 'test-key',
77
+ };
78
+ expect(detectMode(config)).toBe('api');
79
+ expect(mockedAccessSync).not.toHaveBeenCalled();
80
+ });
81
+ });
82
+ // ─── Auto-detection split (IU-40) ────────────────────────────────────────────
83
+ describe('detectSplitMode', () => {
84
+ it('returns split when both filesystem and API are available', () => {
85
+ mockedAccessSync.mockImplementation(() => undefined);
86
+ const config = {
87
+ enabled: true,
88
+ mode: 'auto',
89
+ configPath: '/project/kywi.config.ts',
90
+ baseUrl: 'http://localhost:3000/api/v1',
91
+ apiKey: 'test-key',
92
+ };
93
+ const result = detectSplitMode(config);
94
+ expect(result.configMode).toBe('filesystem');
95
+ expect(result.dataMode).toBe('api');
96
+ });
97
+ it('returns filesystem-only when no API credentials', () => {
98
+ mockedAccessSync.mockImplementation(() => undefined);
99
+ const config = {
100
+ enabled: true,
101
+ mode: 'auto',
102
+ configPath: '/project/kywi.config.ts',
103
+ };
104
+ const result = detectSplitMode(config);
105
+ expect(result.configMode).toBe('filesystem');
106
+ expect(result.dataMode).toBe('filesystem');
107
+ });
108
+ it('returns api-only when no writable config file', () => {
109
+ mockedAccessSync.mockImplementation(() => {
110
+ throw new Error('EACCES');
111
+ });
112
+ const config = {
113
+ enabled: true,
114
+ mode: 'auto',
115
+ configPath: '/project/kywi.config.ts',
116
+ baseUrl: 'http://localhost:3000/api/v1',
117
+ apiKey: 'test-key',
118
+ };
119
+ const result = detectSplitMode(config);
120
+ expect(result.configMode).toBe('api');
121
+ expect(result.dataMode).toBe('api');
122
+ });
123
+ it('returns explicit modes when not auto', () => {
124
+ const config = {
125
+ enabled: true,
126
+ mode: 'filesystem',
127
+ configPath: '/project/kywi.config.ts',
128
+ };
129
+ const result = detectSplitMode(config);
130
+ expect(result.configMode).toBe('filesystem');
131
+ expect(result.dataMode).toBe('filesystem');
132
+ });
133
+ });
134
+ //# sourceMappingURL=auto-detect.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-detect.test.js","sourceRoot":"","sources":["../../src/__tests__/auto-detect.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=config.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/config.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,72 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { defineMcpConfig } from '../config.js';
3
+ import { textResult, errorResult } from '../shared.js';
4
+ describe('defineMcpConfig', () => {
5
+ it('returns the config object unchanged', () => {
6
+ const config = {
7
+ site: {
8
+ enabled: true,
9
+ baseUrl: 'http://localhost:3000',
10
+ apiKey: 'test-key',
11
+ },
12
+ };
13
+ expect(defineMcpConfig(config)).toBe(config);
14
+ });
15
+ it('accepts developer config', () => {
16
+ const config = {
17
+ developer: {
18
+ enabled: true,
19
+ mode: 'filesystem',
20
+ },
21
+ };
22
+ const result = defineMcpConfig(config);
23
+ expect(result.developer?.enabled).toBe(true);
24
+ expect(result.developer?.mode).toBe('filesystem');
25
+ });
26
+ it('accepts combined site and developer config', () => {
27
+ const config = {
28
+ site: {
29
+ enabled: true,
30
+ baseUrl: 'http://localhost:3000',
31
+ apiKey: 'key-1',
32
+ },
33
+ developer: {
34
+ enabled: false,
35
+ mode: 'auto',
36
+ },
37
+ };
38
+ const result = defineMcpConfig(config);
39
+ expect(result.site?.enabled).toBe(true);
40
+ expect(result.developer?.enabled).toBe(false);
41
+ });
42
+ });
43
+ describe('textResult', () => {
44
+ it('wraps data as JSON text content', () => {
45
+ const result = textResult({ foo: 'bar' });
46
+ expect(result.content).toHaveLength(1);
47
+ expect(result.content[0].type).toBe('text');
48
+ expect(JSON.parse(result.content[0].text)).toEqual({ foo: 'bar' });
49
+ });
50
+ it('pretty-prints JSON with 2-space indent', () => {
51
+ const result = textResult({ a: 1 });
52
+ expect(result.content[0].text).toBe(JSON.stringify({ a: 1 }, null, 2));
53
+ });
54
+ it('handles arrays', () => {
55
+ const result = textResult([1, 2, 3]);
56
+ expect(JSON.parse(result.content[0].text)).toEqual([1, 2, 3]);
57
+ });
58
+ it('handles null', () => {
59
+ const result = textResult(null);
60
+ expect(result.content[0].text).toBe('null');
61
+ });
62
+ });
63
+ describe('errorResult', () => {
64
+ it('wraps message as text content with isError flag', () => {
65
+ const result = errorResult('Something went wrong');
66
+ expect(result.content).toHaveLength(1);
67
+ expect(result.content[0].type).toBe('text');
68
+ expect(result.content[0].text).toBe('Something went wrong');
69
+ expect(result.isError).toBe(true);
70
+ });
71
+ });
72
+ //# sourceMappingURL=config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/__tests__/config.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=developer-mutation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"developer-mutation.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/developer-mutation.test.ts"],"names":[],"mappings":""}