create-mcp-kit 0.0.5 → 0.0.6
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 +2 -2
- package/template/server-js/package.json.hbs +3 -2
- package/template/server-js/src/services/web.js.hbs +1 -1
- package/template/server-js/tests/utils.js +16 -0
- package/template/server-js/vitest.config.js.hbs +12 -0
- package/template/server-js/vitest.global.js.hbs +25 -0
- package/template/server-js/vitest.setup.js.hbs +31 -8
- package/template/server-ts/package.json.hbs +5 -4
- package/template/server-ts/src/services/web.ts.hbs +1 -1
- package/template/server-ts/tests/utils.ts +20 -0
- package/template/server-ts/vitest.config.ts.hbs +12 -0
- package/template/server-ts/vitest.global.ts.hbs +25 -0
- package/template/server-ts/vitest.setup.ts.hbs +31 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-mcp-kit",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "create mcp tool kit",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "zhensherlock",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"gradient-string": "^3.0.0",
|
|
44
44
|
"handlebars": "^4.7.8",
|
|
45
45
|
"picocolors": "^1.1.1",
|
|
46
|
-
"@mcp-tool-kit/shared": "^0.0.
|
|
46
|
+
"@mcp-tool-kit/shared": "^0.0.7"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {},
|
|
49
49
|
"scripts": {
|
|
@@ -31,7 +31,8 @@
|
|
|
31
31
|
{{/if}}
|
|
32
32
|
{{#if (includes plugins 'vitest')}}
|
|
33
33
|
"test": "vitest run",
|
|
34
|
-
"
|
|
34
|
+
"report": "c8 report --reporter=lcov --reporter=html",
|
|
35
|
+
"coverage": "rimraf coverage && npm run test && npm run report",
|
|
35
36
|
{{/if}}
|
|
36
37
|
{{#if (includes plugins 'changelog')}}
|
|
37
38
|
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 -n changelog-option.js",
|
|
@@ -54,7 +55,7 @@
|
|
|
54
55
|
"@commitlint/config-conventional": "^19.8.1",
|
|
55
56
|
{{/if}}
|
|
56
57
|
{{#if (includes plugins 'inspector')}}
|
|
57
|
-
"@modelcontextprotocol/inspector": "^0.16.
|
|
58
|
+
"@modelcontextprotocol/inspector": "^0.16.3",
|
|
58
59
|
{{/if}}
|
|
59
60
|
{{#if (includes plugins 'vitest')}}
|
|
60
61
|
"@vitest/coverage-v8": "^3.2.4",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{{#if (or (includes transports 'streamable') (includes transports 'sse'))}}
|
|
2
2
|
{{#if (includes transports 'streamable')}}
|
|
3
|
-
|
|
3
|
+
import { nanoid } from 'nanoid'
|
|
4
4
|
{{/if}}
|
|
5
5
|
import express from 'express'
|
|
6
6
|
{{#if (includes transports 'streamable')}}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function waitForValue(getterFn, checkInterval = 100, timeout = 10000) {
|
|
2
|
+
return new Promise((resolve, reject) => {
|
|
3
|
+
const start = Date.now()
|
|
4
|
+
|
|
5
|
+
const intervalId = setInterval(() => {
|
|
6
|
+
const value = getterFn()
|
|
7
|
+
if (value) {
|
|
8
|
+
clearInterval(intervalId)
|
|
9
|
+
resolve(value)
|
|
10
|
+
} else if (Date.now() - start > timeout) {
|
|
11
|
+
clearInterval(intervalId)
|
|
12
|
+
reject(new Error('Timeout waiting for value'))
|
|
13
|
+
}
|
|
14
|
+
}, checkInterval)
|
|
15
|
+
})
|
|
16
|
+
}
|
|
@@ -3,10 +3,22 @@ import { defineConfig } from 'vitest/config'
|
|
|
3
3
|
|
|
4
4
|
export default defineConfig({
|
|
5
5
|
test: {
|
|
6
|
+
{{#if (or (includes transports 'streamable') (includes transports 'sse'))}}
|
|
7
|
+
globalSetup: ['./vitest.global.js'],
|
|
8
|
+
{{/if}}
|
|
6
9
|
setupFiles: ['./vitest.setup.js'],
|
|
7
10
|
coverage: {
|
|
8
11
|
include: ['src/**/*.js'],
|
|
9
12
|
},
|
|
13
|
+
{{#if (or (includes transports 'streamable') (includes transports 'sse'))}}
|
|
14
|
+
pool: 'threads',
|
|
15
|
+
poolOptions: {
|
|
16
|
+
threads: {
|
|
17
|
+
maxThreads: 1,
|
|
18
|
+
minThreads: 1,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
{{/if}}
|
|
10
22
|
},
|
|
11
23
|
})
|
|
12
24
|
{{/if}}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{{#if (and (includes plugins 'vitest') (or (includes transports 'streamable') (includes transports 'sse')))}}
|
|
2
|
+
import { spawn } from 'child_process'
|
|
3
|
+
import { waitForValue } from './tests/utils.js'
|
|
4
|
+
|
|
5
|
+
export default async function setup() {
|
|
6
|
+
const webProcess = spawn('c8', ['--reporter=lcov', '--reporter=text', 'node', './src/index.js', 'web'], {
|
|
7
|
+
stdio: 'pipe',
|
|
8
|
+
env: {
|
|
9
|
+
...process.env,
|
|
10
|
+
NODE_V8_COVERAGE: './coverage/tmp',
|
|
11
|
+
},
|
|
12
|
+
})
|
|
13
|
+
let webStarted = false
|
|
14
|
+
webProcess.stdout?.on('data', async data => {
|
|
15
|
+
const output = data.toString()
|
|
16
|
+
if (output.includes('MCP server started')) {
|
|
17
|
+
webStarted = true
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
await waitForValue(() => webStarted)
|
|
21
|
+
return () => {
|
|
22
|
+
webProcess.kill('SIGINT')
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
{{/if}}
|
|
@@ -1,21 +1,44 @@
|
|
|
1
1
|
{{#if (includes plugins 'vitest')}}
|
|
2
2
|
import 'dotenv/config'
|
|
3
3
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
|
|
4
|
+
{{#if (includes transports 'stdio')}}
|
|
4
5
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'
|
|
6
|
+
{{/if}}
|
|
7
|
+
{{#if (includes transports 'streamable')}}
|
|
8
|
+
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
|
|
9
|
+
{{/if}}
|
|
10
|
+
{{#if (includes transports 'sse')}}
|
|
11
|
+
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'
|
|
12
|
+
{{/if}}
|
|
5
13
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
14
|
+
const client = new Client({
|
|
15
|
+
name: 'test-mcp-client',
|
|
16
|
+
version: '1.0.0',
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
{{#if (includes transports 'stdio')}}
|
|
20
|
+
const stdioClientTransport = new StdioClientTransport({
|
|
21
|
+
command: 'c8',
|
|
22
|
+
args: ['--reporter=lcov', '--reporter=text', 'node', './src/index.js'],
|
|
9
23
|
env: {
|
|
10
24
|
...process.env,
|
|
11
25
|
NODE_V8_COVERAGE: './coverage/tmp',
|
|
12
26
|
},
|
|
13
27
|
})
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
28
|
+
await client.connect(stdioClientTransport)
|
|
29
|
+
|
|
30
|
+
{{/if}}
|
|
31
|
+
{{#if (includes transports 'streamable')}}
|
|
32
|
+
const streamableBaseUrl = new URL('http://localhost:8401/mcp')
|
|
33
|
+
const streamableClientTransport = new StreamableHTTPClientTransport(new URL(streamableBaseUrl))
|
|
34
|
+
await client.connect(streamableClientTransport)
|
|
35
|
+
|
|
36
|
+
{{/if}}
|
|
37
|
+
{{#if (includes transports 'sse')}}
|
|
38
|
+
const sseBaseUrl = new URL('http://localhost:8401/sse')
|
|
39
|
+
const sseClientTransport = new SSEClientTransport(new URL(sseBaseUrl))
|
|
40
|
+
await client.connect(sseClientTransport)
|
|
19
41
|
|
|
42
|
+
{{/if}}
|
|
20
43
|
global.client = client
|
|
21
44
|
{{/if}}
|
|
@@ -31,7 +31,8 @@
|
|
|
31
31
|
{{/if}}
|
|
32
32
|
{{#if (includes plugins 'vitest')}}
|
|
33
33
|
"test": "vitest run",
|
|
34
|
-
"
|
|
34
|
+
"report": "c8 report --reporter=lcov --reporter=html",
|
|
35
|
+
"coverage": "rimraf coverage && npm run test && npm run report",
|
|
35
36
|
{{/if}}
|
|
36
37
|
{{#if (includes plugins 'changelog')}}
|
|
37
38
|
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 -n changelog-option.js",
|
|
@@ -54,15 +55,15 @@
|
|
|
54
55
|
"@commitlint/config-conventional": "^19.8.1",
|
|
55
56
|
{{/if}}
|
|
56
57
|
{{#if (includes plugins 'inspector')}}
|
|
57
|
-
"@modelcontextprotocol/inspector": "^0.16.
|
|
58
|
+
"@modelcontextprotocol/inspector": "^0.16.3",
|
|
58
59
|
{{/if}}
|
|
59
60
|
{{#if (or (includes transports 'streamable') (includes transports 'sse'))}}
|
|
60
61
|
"@types/express": "^5.0.3",
|
|
61
62
|
{{/if}}
|
|
62
63
|
"@types/yargs": "^17.0.33",
|
|
63
64
|
{{#if (includes plugins 'style')}}
|
|
64
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
65
|
-
"@typescript-eslint/parser": "^8.
|
|
65
|
+
"@typescript-eslint/eslint-plugin": "^8.39.1",
|
|
66
|
+
"@typescript-eslint/parser": "^8.39.1",
|
|
66
67
|
{{/if}}
|
|
67
68
|
{{#if (includes plugins 'vitest')}}
|
|
68
69
|
"@vitest/coverage-v8": "^3.2.4",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{{#if (or (includes transports 'streamable') (includes transports 'sse'))}}
|
|
2
2
|
{{#if (includes transports 'streamable')}}
|
|
3
|
-
|
|
3
|
+
import { nanoid } from 'nanoid'
|
|
4
4
|
{{/if}}
|
|
5
5
|
import express from 'express'
|
|
6
6
|
{{#if (includes transports 'streamable')}}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export function waitForValue<T>(
|
|
2
|
+
getterFn: () => T | undefined | null,
|
|
3
|
+
checkInterval = 100,
|
|
4
|
+
timeout = 10000,
|
|
5
|
+
): Promise<T> {
|
|
6
|
+
return new Promise((resolve, reject) => {
|
|
7
|
+
const start = Date.now()
|
|
8
|
+
|
|
9
|
+
const intervalId = setInterval(() => {
|
|
10
|
+
const value = getterFn()
|
|
11
|
+
if (value) {
|
|
12
|
+
clearInterval(intervalId)
|
|
13
|
+
resolve(value)
|
|
14
|
+
} else if (Date.now() - start > timeout) {
|
|
15
|
+
clearInterval(intervalId)
|
|
16
|
+
reject(new Error('Timeout waiting for value'))
|
|
17
|
+
}
|
|
18
|
+
}, checkInterval)
|
|
19
|
+
})
|
|
20
|
+
}
|
|
@@ -3,10 +3,22 @@ import { defineConfig } from 'vitest/config'
|
|
|
3
3
|
|
|
4
4
|
export default defineConfig({
|
|
5
5
|
test: {
|
|
6
|
+
{{#if (or (includes transports 'streamable') (includes transports 'sse'))}}
|
|
7
|
+
globalSetup: ['./vitest.global.ts'],
|
|
8
|
+
{{/if}}
|
|
6
9
|
setupFiles: ['./vitest.setup.ts'],
|
|
7
10
|
coverage: {
|
|
8
11
|
include: ['src/**/*.ts'],
|
|
9
12
|
},
|
|
13
|
+
{{#if (or (includes transports 'streamable') (includes transports 'sse'))}}
|
|
14
|
+
pool: 'threads',
|
|
15
|
+
poolOptions: {
|
|
16
|
+
threads: {
|
|
17
|
+
maxThreads: 1,
|
|
18
|
+
minThreads: 1,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
{{/if}}
|
|
10
22
|
},
|
|
11
23
|
})
|
|
12
24
|
{{/if}}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{{#if (and (includes plugins 'vitest') (or (includes transports 'streamable') (includes transports 'sse')))}}
|
|
2
|
+
import { spawn } from 'child_process'
|
|
3
|
+
import { waitForValue } from './tests/utils'
|
|
4
|
+
|
|
5
|
+
export default async function setup() {
|
|
6
|
+
const webProcess = spawn('c8', ['--reporter=lcov', '--reporter=text', 'tsx', './src/index.ts', 'web'], {
|
|
7
|
+
stdio: 'pipe',
|
|
8
|
+
env: {
|
|
9
|
+
...(process.env as Record<string, string>),
|
|
10
|
+
NODE_V8_COVERAGE: './coverage/tmp',
|
|
11
|
+
},
|
|
12
|
+
})
|
|
13
|
+
let webStarted = false
|
|
14
|
+
webProcess.stdout?.on('data', async data => {
|
|
15
|
+
const output = data.toString()
|
|
16
|
+
if (output.includes('MCP server started')) {
|
|
17
|
+
webStarted = true
|
|
18
|
+
}
|
|
19
|
+
})
|
|
20
|
+
await waitForValue(() => webStarted)
|
|
21
|
+
return () => {
|
|
22
|
+
webProcess.kill('SIGINT')
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
{{/if}}
|
|
@@ -1,27 +1,44 @@
|
|
|
1
1
|
{{#if (includes plugins 'vitest')}}
|
|
2
2
|
import 'dotenv/config'
|
|
3
3
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js'
|
|
4
|
+
{{#if (includes transports 'stdio')}}
|
|
4
5
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'
|
|
6
|
+
{{/if}}
|
|
7
|
+
{{#if (includes transports 'streamable')}}
|
|
8
|
+
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
|
|
9
|
+
{{/if}}
|
|
10
|
+
{{#if (includes transports 'sse')}}
|
|
11
|
+
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'
|
|
12
|
+
{{/if}}
|
|
5
13
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
],
|
|
14
|
+
const client = new Client({
|
|
15
|
+
name: 'test-mcp-client',
|
|
16
|
+
version: '1.0.0',
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
{{#if (includes transports 'stdio')}}
|
|
20
|
+
const stdioClientTransport = new StdioClientTransport({
|
|
21
|
+
command: 'c8',
|
|
22
|
+
args: ['--reporter=lcov', '--reporter=text', 'tsx', './src/index.ts'],
|
|
15
23
|
env: {
|
|
16
24
|
...process.env as Record<string, string>,
|
|
17
25
|
NODE_V8_COVERAGE: './coverage/tmp',
|
|
18
26
|
},
|
|
19
27
|
})
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
28
|
+
await client.connect(stdioClientTransport)
|
|
29
|
+
|
|
30
|
+
{{/if}}
|
|
31
|
+
{{#if (includes transports 'streamable')}}
|
|
32
|
+
const streamableBaseUrl = new URL('http://localhost:8401/mcp')
|
|
33
|
+
const streamableClientTransport = new StreamableHTTPClientTransport(new URL(streamableBaseUrl))
|
|
34
|
+
await client.connect(streamableClientTransport)
|
|
35
|
+
|
|
36
|
+
{{/if}}
|
|
37
|
+
{{#if (includes transports 'sse')}}
|
|
38
|
+
const sseBaseUrl = new URL('http://localhost:8401/sse')
|
|
39
|
+
const sseClientTransport = new SSEClientTransport(new URL(sseBaseUrl))
|
|
40
|
+
await client.connect(sseClientTransport)
|
|
25
41
|
|
|
42
|
+
{{/if}}
|
|
26
43
|
global.client = client
|
|
27
44
|
{{/if}}
|