mcpx-framework 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/LICENSE +21 -0
- package/README.md +215 -0
- package/dist/cli/build.d.ts +1 -0
- package/dist/cli/build.js +7 -0
- package/dist/cli/build.js.map +1 -0
- package/dist/cli/dev.d.ts +1 -0
- package/dist/cli/dev.js +55 -0
- package/dist/cli/dev.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +31 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +1 -0
- package/dist/cli/init.js +27 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/core/index.d.ts +2 -0
- package/dist/core/index.js +2 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/server.d.ts +2 -0
- package/dist/core/server.js +101 -0
- package/dist/core/server.js.map +1 -0
- package/dist/core/types.d.ts +52 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/package.json +61 -0
- package/templates/basic/package.json +16 -0
- package/templates/basic/src/index.ts +19 -0
- package/templates/basic/tsconfig.json +15 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MCPX
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# MCPX
|
|
2
|
+
|
|
3
|
+
**Build MCP servers in minutes, not hours.** One TypeScript function = one MCP tool. Zero boilerplate.
|
|
4
|
+
|
|
5
|
+
> Next.js for MCP — a framework on top of the Model Context Protocol that prioritizes developer experience.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install mcpx-framework
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Why MCPX?
|
|
12
|
+
|
|
13
|
+
The official MCP SDK requires you to manage transports, handle JSON-RPC, and write repetitive boilerplate for every tool. MCPX reduces all of that to a single function per tool.
|
|
14
|
+
|
|
15
|
+
### Without MCPX (raw MCP SDK — ~40 lines)
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
19
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
20
|
+
import { z } from 'zod';
|
|
21
|
+
|
|
22
|
+
const server = new McpServer({ name: 'my-tools', version: '1.0.0' });
|
|
23
|
+
|
|
24
|
+
server.tool(
|
|
25
|
+
'add',
|
|
26
|
+
'Add two numbers',
|
|
27
|
+
{ a: z.number().describe('First number'), b: z.number().describe('Second number') },
|
|
28
|
+
async ({ a, b }) => ({
|
|
29
|
+
content: [{ type: 'text', text: `${a} + ${b} = ${a + b}` }],
|
|
30
|
+
})
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
server.tool(
|
|
34
|
+
'greet',
|
|
35
|
+
'Greet someone',
|
|
36
|
+
{ name: z.string().describe('Name to greet') },
|
|
37
|
+
async ({ name }) => ({
|
|
38
|
+
content: [{ type: 'text', text: `Hello, ${name}!` }],
|
|
39
|
+
})
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const transport = new StdioServerTransport();
|
|
43
|
+
await server.connect(transport);
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### With MCPX (~15 lines)
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { mcpx } from 'mcpx-framework';
|
|
50
|
+
|
|
51
|
+
const server = mcpx({ name: 'my-tools', version: '1.0.0' });
|
|
52
|
+
|
|
53
|
+
server
|
|
54
|
+
.tool({
|
|
55
|
+
name: 'add',
|
|
56
|
+
description: 'Add two numbers',
|
|
57
|
+
parameters: { a: { type: 'number' }, b: { type: 'number' } },
|
|
58
|
+
handler: async ({ a, b }) => `${a} + ${b} = ${a + b}`,
|
|
59
|
+
})
|
|
60
|
+
.tool({
|
|
61
|
+
name: 'greet',
|
|
62
|
+
description: 'Greet someone',
|
|
63
|
+
parameters: { name: { type: 'string' } },
|
|
64
|
+
handler: async ({ name }) => `Hello, ${name}!`,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
server.start();
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**70% less code. Zero protocol knowledge required. No Zod imports.**
|
|
71
|
+
|
|
72
|
+
## Quick Start
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# Create a new MCP server project
|
|
76
|
+
npx mcpx init my-mcp
|
|
77
|
+
cd my-mcp
|
|
78
|
+
npm install
|
|
79
|
+
|
|
80
|
+
# Start developing with hot reload
|
|
81
|
+
npx mcpx dev
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Your MCP server is now running. Add it to Claude:
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"mcpServers": {
|
|
89
|
+
"my-mcp": {
|
|
90
|
+
"command": "node",
|
|
91
|
+
"args": ["dist/index.js"],
|
|
92
|
+
"cwd": "/path/to/my-mcp"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Examples
|
|
99
|
+
|
|
100
|
+
### Calculator (minimal — 2 tools, 20 lines)
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
import { mcpx } from 'mcpx-framework';
|
|
104
|
+
|
|
105
|
+
const server = mcpx({ name: 'calculator', version: '0.1.0' });
|
|
106
|
+
|
|
107
|
+
server
|
|
108
|
+
.tool({
|
|
109
|
+
name: 'add',
|
|
110
|
+
description: 'Add two numbers',
|
|
111
|
+
parameters: { a: { type: 'number' }, b: { type: 'number' } },
|
|
112
|
+
handler: async ({ a, b }) => `${a} + ${b} = ${a + b}`,
|
|
113
|
+
})
|
|
114
|
+
.tool({
|
|
115
|
+
name: 'multiply',
|
|
116
|
+
description: 'Multiply two numbers',
|
|
117
|
+
parameters: { a: { type: 'number' }, b: { type: 'number' } },
|
|
118
|
+
handler: async ({ a, b }) => `${a} × ${b} = ${a * b}`,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
server.start();
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### GitHub API (2 tools, 40 lines)
|
|
125
|
+
|
|
126
|
+
Search repositories and get issues — see [examples/github.ts](examples/github.ts).
|
|
127
|
+
|
|
128
|
+
### Filesystem (3 tools, 50 lines)
|
|
129
|
+
|
|
130
|
+
Read, write, and list local files — see [examples/filesystem.ts](examples/filesystem.ts).
|
|
131
|
+
|
|
132
|
+
### Web Fetch (2 tools, 60 lines)
|
|
133
|
+
|
|
134
|
+
Fetch URLs and inspect HTTP headers — see [examples/web-fetch.ts](examples/web-fetch.ts).
|
|
135
|
+
|
|
136
|
+
## CLI
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
mcpx init [name] # Scaffold a new MCP server
|
|
140
|
+
mcpx dev # Hot-reload dev mode (watches src/, auto-restarts)
|
|
141
|
+
mcpx build # Production build → dist/
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## API
|
|
145
|
+
|
|
146
|
+
### `mcpx(options)`
|
|
147
|
+
|
|
148
|
+
Creates a new MCP server instance.
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
const server = mcpx({
|
|
152
|
+
name: 'my-server', // Required — displayed in Claude
|
|
153
|
+
version: '1.0.0', // Required — semver
|
|
154
|
+
description: '...', // Optional — shown in Claude's tool list
|
|
155
|
+
});
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### `server.tool(definition)`
|
|
159
|
+
|
|
160
|
+
Register a tool. Returns the server instance for chaining.
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
server.tool({
|
|
164
|
+
name: 'do_thing', // Unique tool name (snake_case recommended)
|
|
165
|
+
description: 'Does a thing', // Shown to Claude — be specific
|
|
166
|
+
parameters: { // Input schema
|
|
167
|
+
input: {
|
|
168
|
+
type: 'string', // string | number | boolean | array | object
|
|
169
|
+
description: 'The input', // Optional — helps Claude understand
|
|
170
|
+
required: false, // Optional — defaults to true
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
handler: async (params) => { // Your logic here
|
|
174
|
+
return 'done'; // Return string, object, or CallToolResult
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### `server.resource(definition)`
|
|
180
|
+
|
|
181
|
+
Register a resource (exposes data to Claude as contextual content).
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
server.resource({
|
|
185
|
+
name: 'config',
|
|
186
|
+
description: 'Application configuration',
|
|
187
|
+
uri: 'config://app', // Optional — auto-generated if omitted
|
|
188
|
+
handler: async () => ({
|
|
189
|
+
content: JSON.stringify(config),
|
|
190
|
+
mimeType: 'application/json', // Optional — defaults to text/plain
|
|
191
|
+
}),
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Return values
|
|
196
|
+
|
|
197
|
+
Handlers can return any of these:
|
|
198
|
+
|
|
199
|
+
| Return type | Result |
|
|
200
|
+
|---|---|
|
|
201
|
+
| `string` | Sent as text content |
|
|
202
|
+
| `object` / `array` | JSON-stringified (pretty-printed) |
|
|
203
|
+
| `{ content: [...] }` | Passed through as raw MCP content |
|
|
204
|
+
|
|
205
|
+
### `server.start()`
|
|
206
|
+
|
|
207
|
+
Starts the server via stdio transport (standard MCP). Call this once, at the end.
|
|
208
|
+
|
|
209
|
+
## Star History
|
|
210
|
+
|
|
211
|
+
[](https://star-history.com/#Kasyou/mcpx-framework&Date)
|
|
212
|
+
|
|
213
|
+
## License
|
|
214
|
+
|
|
215
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function build(): Promise<void>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
export async function build() {
|
|
3
|
+
console.log(' 📦 Building...');
|
|
4
|
+
execSync('npx --no-install tsc', { stdio: 'inherit', cwd: process.cwd() });
|
|
5
|
+
console.log(' ✅ Build complete. Output in dist/\n');
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAChC,QAAQ,CAAC,sBAAsB,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function dev(entry: string): Promise<void>;
|
package/dist/cli/dev.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { watch } from 'chokidar';
|
|
3
|
+
import { join, relative } from 'node:path';
|
|
4
|
+
export async function dev(entry) {
|
|
5
|
+
const cwd = process.cwd();
|
|
6
|
+
const srcDir = join(cwd, 'src');
|
|
7
|
+
// Derive output path: src/foo.ts → dist/foo.js
|
|
8
|
+
const rel = relative(cwd, join(cwd, entry));
|
|
9
|
+
const outFile = join(cwd, 'dist', rel.replace(/^src[\\/]/, '').replace(/\.ts$/, '.js'));
|
|
10
|
+
console.log(' 🔥 MCPX dev server starting...');
|
|
11
|
+
console.log(` 📁 Watching: ${srcDir}`);
|
|
12
|
+
console.log(` 🎯 Entry: ${rel} → ${relative(cwd, outFile)}\n`);
|
|
13
|
+
let child = null;
|
|
14
|
+
const start = () => {
|
|
15
|
+
if (child) {
|
|
16
|
+
child.kill();
|
|
17
|
+
child = null;
|
|
18
|
+
}
|
|
19
|
+
child = spawn('node', [outFile], { stdio: 'inherit', cwd });
|
|
20
|
+
child.on('exit', () => { child = null; });
|
|
21
|
+
};
|
|
22
|
+
const build = (label) => {
|
|
23
|
+
if (label)
|
|
24
|
+
console.log(` 🔄 ${label}`);
|
|
25
|
+
const tsc = spawn('npx', ['tsc'], { stdio: 'pipe', cwd });
|
|
26
|
+
let stderr = '';
|
|
27
|
+
tsc.stderr?.on('data', (d) => { stderr += d.toString(); });
|
|
28
|
+
tsc.on('exit', (code) => {
|
|
29
|
+
if (code === 0) {
|
|
30
|
+
if (stderr)
|
|
31
|
+
process.stderr.write(stderr);
|
|
32
|
+
if (!label)
|
|
33
|
+
console.log(' 🚀 Server started\n');
|
|
34
|
+
start();
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
process.stderr.write(stderr);
|
|
38
|
+
console.error(' ❌ Build failed — waiting for changes...\n');
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
build();
|
|
43
|
+
let timeout = null;
|
|
44
|
+
watch(srcDir, {
|
|
45
|
+
ignored: /(^|[\\/])\../,
|
|
46
|
+
persistent: true,
|
|
47
|
+
}).on('all', (_event, filePath) => {
|
|
48
|
+
if (timeout)
|
|
49
|
+
clearTimeout(timeout);
|
|
50
|
+
timeout = setTimeout(() => {
|
|
51
|
+
build(relative(cwd, filePath));
|
|
52
|
+
}, 200);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=dev.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
const program = new Command()
|
|
4
|
+
.name('mcpx')
|
|
5
|
+
.description('Build MCP servers in minutes, not hours')
|
|
6
|
+
.version('0.1.0');
|
|
7
|
+
program
|
|
8
|
+
.command('init [name]')
|
|
9
|
+
.description('Create a new MCP server project')
|
|
10
|
+
.option('-t, --template <template>', 'Template to use', 'basic')
|
|
11
|
+
.action(async (name, options) => {
|
|
12
|
+
const { init } = await import('./init.js');
|
|
13
|
+
await init(name || 'my-mcp', options.template);
|
|
14
|
+
});
|
|
15
|
+
program
|
|
16
|
+
.command('dev')
|
|
17
|
+
.description('Start development mode with hot reload')
|
|
18
|
+
.option('-e, --entry <entry>', 'Entry file', 'src/index.ts')
|
|
19
|
+
.action(async (options) => {
|
|
20
|
+
const { dev } = await import('./dev.js');
|
|
21
|
+
await dev(options.entry);
|
|
22
|
+
});
|
|
23
|
+
program
|
|
24
|
+
.command('build')
|
|
25
|
+
.description('Build for production')
|
|
26
|
+
.action(async () => {
|
|
27
|
+
const { build } = await import('./build.js');
|
|
28
|
+
await build();
|
|
29
|
+
});
|
|
30
|
+
program.parse();
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE;KAC1B,IAAI,CAAC,MAAM,CAAC;KACZ,WAAW,CAAC,yCAAyC,CAAC;KACtD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,iCAAiC,CAAC;KAC9C,MAAM,CAAC,2BAA2B,EAAE,iBAAiB,EAAE,OAAO,CAAC;KAC/D,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;IAC9B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;IAC3C,MAAM,IAAI,CAAC,IAAI,IAAI,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;AACjD,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,wCAAwC,CAAC;KACrD,MAAM,CAAC,qBAAqB,EAAE,YAAY,EAAE,cAAc,CAAC;KAC3D,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAC;IACzC,MAAM,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,sBAAsB,CAAC;KACnC,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;IAC7C,MAAM,KAAK,EAAE,CAAC;AAChB,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function init(name: string, template: string): Promise<void>;
|
package/dist/cli/init.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { cp, mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { join, dirname, resolve, basename } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
export async function init(name, template) {
|
|
6
|
+
const projectDir = resolve(process.cwd(), name);
|
|
7
|
+
const pkgName = basename(projectDir);
|
|
8
|
+
const templateDir = join(__dirname, '..', '..', 'templates', template);
|
|
9
|
+
await mkdir(projectDir, { recursive: true });
|
|
10
|
+
await cp(templateDir, projectDir, { recursive: true });
|
|
11
|
+
const pkgPath = join(projectDir, 'package.json');
|
|
12
|
+
const pkgContent = await readFile(pkgPath, 'utf-8');
|
|
13
|
+
const pkg = JSON.parse(pkgContent);
|
|
14
|
+
pkg.name = pkgName;
|
|
15
|
+
await writeFile(pkgPath, JSON.stringify(pkg, null, 2));
|
|
16
|
+
// Replace TEMPLATE_NAME in source files
|
|
17
|
+
const srcIndex = join(projectDir, 'src', 'index.ts');
|
|
18
|
+
let srcContent = await readFile(srcIndex, 'utf-8');
|
|
19
|
+
srcContent = srcContent.replace(/TEMPLATE_NAME/g, pkgName);
|
|
20
|
+
await writeFile(srcIndex, srcContent);
|
|
21
|
+
console.log(`\n ✨ MCP server project created at ${projectDir}`);
|
|
22
|
+
console.log(`\n Next steps:`);
|
|
23
|
+
console.log(` cd ${projectDir}`);
|
|
24
|
+
console.log(` npm install`);
|
|
25
|
+
console.log(` npx mcpx dev\n`);
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/cli/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAY,EAAE,QAAgB;IACvD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;IACrC,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;IAEvE,MAAM,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEvD,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACpD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACnC,GAAG,CAAC,IAAI,GAAG,OAAO,CAAC;IACnB,MAAM,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAEvD,wCAAwC;IACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC;IACrD,IAAI,UAAU,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACnD,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;IAC3D,MAAM,SAAS,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAEtC,OAAO,CAAC,GAAG,CAAC,uCAAuC,UAAU,EAAE,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC/B,OAAO,CAAC,GAAG,CAAC,UAAU,UAAU,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC/B,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
function toZodSchema(params) {
|
|
5
|
+
const shape = {};
|
|
6
|
+
for (const [key, def] of Object.entries(params)) {
|
|
7
|
+
let schema;
|
|
8
|
+
switch (def.type) {
|
|
9
|
+
case 'string':
|
|
10
|
+
schema = z.string();
|
|
11
|
+
break;
|
|
12
|
+
case 'number':
|
|
13
|
+
schema = z.number();
|
|
14
|
+
break;
|
|
15
|
+
case 'boolean':
|
|
16
|
+
schema = z.boolean();
|
|
17
|
+
break;
|
|
18
|
+
case 'array':
|
|
19
|
+
schema = def.items ? z.array(toZodItem(def.items)) : z.array(z.unknown());
|
|
20
|
+
break;
|
|
21
|
+
case 'object':
|
|
22
|
+
schema = z.record(z.string(), z.unknown());
|
|
23
|
+
break;
|
|
24
|
+
default:
|
|
25
|
+
schema = z.unknown();
|
|
26
|
+
}
|
|
27
|
+
if (def.description) {
|
|
28
|
+
schema = schema.describe(def.description);
|
|
29
|
+
}
|
|
30
|
+
shape[key] = def.required === false ? schema.optional() : schema;
|
|
31
|
+
}
|
|
32
|
+
return shape;
|
|
33
|
+
}
|
|
34
|
+
function toZodItem(def) {
|
|
35
|
+
switch (def.type) {
|
|
36
|
+
case 'string':
|
|
37
|
+
return z.string();
|
|
38
|
+
case 'number':
|
|
39
|
+
return z.number();
|
|
40
|
+
case 'boolean':
|
|
41
|
+
return z.boolean();
|
|
42
|
+
default:
|
|
43
|
+
return z.unknown();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export function mcpx(options) {
|
|
47
|
+
const server = new McpServer({
|
|
48
|
+
name: options.name,
|
|
49
|
+
version: options.version,
|
|
50
|
+
});
|
|
51
|
+
const instance = {
|
|
52
|
+
tool(def) {
|
|
53
|
+
const paramKeys = Object.keys(def.parameters);
|
|
54
|
+
const zodSchema = paramKeys.length > 0 ? toZodSchema(def.parameters) : undefined;
|
|
55
|
+
const callback = async (args) => {
|
|
56
|
+
try {
|
|
57
|
+
const result = await def.handler(args);
|
|
58
|
+
if (typeof result === 'string') {
|
|
59
|
+
return { content: [{ type: 'text', text: result }] };
|
|
60
|
+
}
|
|
61
|
+
if (result && typeof result === 'object' && 'content' in result) {
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
70
|
+
return {
|
|
71
|
+
isError: true,
|
|
72
|
+
content: [{ type: 'text', text: message }],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
if (zodSchema) {
|
|
77
|
+
server.tool(def.name, def.description, zodSchema, callback);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
server.tool(def.name, def.description, callback);
|
|
81
|
+
}
|
|
82
|
+
return instance;
|
|
83
|
+
},
|
|
84
|
+
resource(def) {
|
|
85
|
+
server.resource(def.name, def.uri || `mcpx://${def.name}`, async () => {
|
|
86
|
+
const result = await def.handler();
|
|
87
|
+
return { contents: [{ uri: def.uri || `mcpx://${def.name}`, mimeType: result.mimeType || 'text/plain', text: result.content }] };
|
|
88
|
+
});
|
|
89
|
+
return instance;
|
|
90
|
+
},
|
|
91
|
+
async start() {
|
|
92
|
+
const transport = new StdioServerTransport();
|
|
93
|
+
await server.connect(transport);
|
|
94
|
+
},
|
|
95
|
+
getServer() {
|
|
96
|
+
return server.server;
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
return instance;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/core/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
export interface ToolParameter {
|
|
4
|
+
type: 'string' | 'number' | 'boolean' | 'array' | 'object';
|
|
5
|
+
description?: string;
|
|
6
|
+
required?: boolean;
|
|
7
|
+
items?: ToolParameter;
|
|
8
|
+
}
|
|
9
|
+
type ParamType<T extends ToolParameter['type']> = T extends 'string' ? string : T extends 'number' ? number : T extends 'boolean' ? boolean : T extends 'array' ? unknown[] : T extends 'object' ? Record<string, unknown> : unknown;
|
|
10
|
+
type RequiredParamKeys<P extends Record<string, ToolParameter>> = {
|
|
11
|
+
[K in keyof P]: P[K] extends {
|
|
12
|
+
required: false;
|
|
13
|
+
} ? never : K;
|
|
14
|
+
}[keyof P];
|
|
15
|
+
type OptionalParamKeys<P extends Record<string, ToolParameter>> = {
|
|
16
|
+
[K in keyof P]: P[K] extends {
|
|
17
|
+
required: false;
|
|
18
|
+
} ? K : never;
|
|
19
|
+
}[keyof P];
|
|
20
|
+
export type InferToolParams<P extends Record<string, ToolParameter>> = {
|
|
21
|
+
[K in RequiredParamKeys<P>]: ParamType<P[K]['type']>;
|
|
22
|
+
} & {
|
|
23
|
+
[K in OptionalParamKeys<P>]?: ParamType<P[K]['type']>;
|
|
24
|
+
};
|
|
25
|
+
export type ToolHandlerResult = Promise<CallToolResult | string | Record<string, unknown> | unknown[]>;
|
|
26
|
+
export interface McpxTool<P extends Record<string, ToolParameter> = Record<string, ToolParameter>> {
|
|
27
|
+
name: string;
|
|
28
|
+
description: string;
|
|
29
|
+
parameters: P;
|
|
30
|
+
handler: (params: InferToolParams<P>) => ToolHandlerResult;
|
|
31
|
+
}
|
|
32
|
+
export interface McpxResource {
|
|
33
|
+
name: string;
|
|
34
|
+
description: string;
|
|
35
|
+
uri?: string;
|
|
36
|
+
handler: () => Promise<{
|
|
37
|
+
content: string;
|
|
38
|
+
mimeType?: string;
|
|
39
|
+
}>;
|
|
40
|
+
}
|
|
41
|
+
export interface McpxOptions {
|
|
42
|
+
name: string;
|
|
43
|
+
version: string;
|
|
44
|
+
description?: string;
|
|
45
|
+
}
|
|
46
|
+
export interface McpxInstance {
|
|
47
|
+
tool<const P extends Record<string, ToolParameter>>(def: McpxTool<P>): McpxInstance;
|
|
48
|
+
resource(def: McpxResource): McpxInstance;
|
|
49
|
+
start(): Promise<void>;
|
|
50
|
+
getServer(): Server;
|
|
51
|
+
}
|
|
52
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":""}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mcpx-framework",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Build MCP servers in minutes, not hours. One function = one MCP tool. Zero boilerplate.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"bin": {
|
|
15
|
+
"mcpx": "./dist/cli/index.js"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"templates"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"dev": "tsc --watch",
|
|
23
|
+
"build": "tsc",
|
|
24
|
+
"typecheck": "tsc --noEmit",
|
|
25
|
+
"test": "vitest run",
|
|
26
|
+
"test:watch": "vitest",
|
|
27
|
+
"prepublishOnly": "npm run build"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=18"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"mcp",
|
|
34
|
+
"model-context-protocol",
|
|
35
|
+
"mcp-server",
|
|
36
|
+
"mcp-framework",
|
|
37
|
+
"ai",
|
|
38
|
+
"claude",
|
|
39
|
+
"llm",
|
|
40
|
+
"anthropic",
|
|
41
|
+
"developer-tools",
|
|
42
|
+
"cli",
|
|
43
|
+
"typescript"
|
|
44
|
+
],
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "https://github.com/Kasyou/mcpx-framework"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/node": "^22.0.0",
|
|
52
|
+
"typescript": "^5.8.0",
|
|
53
|
+
"vitest": "^3.0.0"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
57
|
+
"chokidar": "^4.0.0",
|
|
58
|
+
"commander": "^13.0.0",
|
|
59
|
+
"zod": "^3.25.0"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "TEMPLATE_NAME",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "mcpx dev",
|
|
7
|
+
"build": "mcpx build"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"mcpx-framework": "latest"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"typescript": "^5.8.0",
|
|
14
|
+
"@types/node": "^22.0.0"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { mcpx } from 'mcpx-framework';
|
|
2
|
+
|
|
3
|
+
const server = mcpx({
|
|
4
|
+
name: 'TEMPLATE_NAME',
|
|
5
|
+
version: '0.0.1',
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
server.tool({
|
|
9
|
+
name: 'hello',
|
|
10
|
+
description: 'Say hello to someone',
|
|
11
|
+
parameters: {
|
|
12
|
+
name: { type: 'string', description: 'Name to greet' },
|
|
13
|
+
},
|
|
14
|
+
handler: async ({ name }) => {
|
|
15
|
+
return `Hello, ${name}!`;
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
server.start();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "Node16",
|
|
5
|
+
"moduleResolution": "Node16",
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": "./src",
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"strict": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"skipLibCheck": true
|
|
12
|
+
},
|
|
13
|
+
"include": ["src/**/*.ts"],
|
|
14
|
+
"exclude": ["node_modules", "dist"]
|
|
15
|
+
}
|