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 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
+ [![Star History Chart](https://api.star-history.com/svg?repos=Kasyou/mcpx-framework&type=Date)](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>;
@@ -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,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -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>;
@@ -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,2 @@
1
+ export { mcpx } from './server.js';
2
+ export type { McpxTool, McpxResource, McpxOptions, McpxInstance, ToolParameter } from './types.js';
@@ -0,0 +1,2 @@
1
+ export { mcpx } from './server.js';
2
+ //# sourceMappingURL=index.js.map
@@ -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,2 @@
1
+ import type { McpxInstance, McpxOptions } from './types.js';
2
+ export declare function mcpx(options: McpxOptions): McpxInstance;
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export { mcpx } from './core/index.js';
2
+ export type { McpxTool, McpxResource, McpxOptions, McpxInstance, ToolParameter } from './core/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { mcpx } from './core/index.js';
2
+ //# sourceMappingURL=index.js.map
@@ -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
+ }