@aiready/mcp-server 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.
@@ -0,0 +1,17 @@
1
+
2
+ 
3
+ > @aiready/mcp-server@0.1.0 build /Users/pengcao/projects/aiready/packages/mcp-server
4
+ > tsup src/index.ts --format esm --clean --dts
5
+
6
+ CLI Building entry: src/index.ts
7
+ CLI Using tsconfig: tsconfig.json
8
+ CLI tsup v8.5.1
9
+ CLI Using tsup config: /Users/pengcao/projects/aiready/packages/mcp-server/tsup.config.ts
10
+ CLI Target: node20
11
+ CLI Cleaning output folder
12
+ ESM Build start
13
+ ESM dist/index.js 2.74 KB
14
+ ESM ⚡️ Build success in 29ms
15
+ DTS Build start
16
+ DTS ⚡️ Build success in 2555ms
17
+ DTS dist/index.d.ts 202.00 B
@@ -0,0 +1,11 @@
1
+ /**
2
+ * AIReady MCP Server Implementation
3
+ */
4
+ declare class AIReadyMcpServer {
5
+ private server;
6
+ constructor();
7
+ private setupHandlers;
8
+ run(): Promise<void>;
9
+ }
10
+
11
+ export { AIReadyMcpServer };
package/dist/index.js ADDED
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import {
7
+ CallToolRequestSchema,
8
+ ListToolsRequestSchema
9
+ } from "@modelcontextprotocol/sdk/types.js";
10
+ import { ToolRegistry } from "@aiready/core";
11
+ import chalk from "chalk";
12
+ import "@aiready/pattern-detect";
13
+ import "@aiready/context-analyzer";
14
+ import "@aiready/consistency";
15
+ var AIReadyMcpServer = class {
16
+ constructor() {
17
+ this.server = new Server(
18
+ {
19
+ name: "aiready-server",
20
+ version: "0.1.0"
21
+ },
22
+ {
23
+ capabilities: {
24
+ tools: {}
25
+ }
26
+ }
27
+ );
28
+ this.setupHandlers();
29
+ this.server.onerror = (error) => {
30
+ console.error(chalk.red("[MCP Error]"), error);
31
+ };
32
+ }
33
+ setupHandlers() {
34
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => {
35
+ const providers = ToolRegistry.getAll();
36
+ return {
37
+ tools: providers.map((p) => ({
38
+ name: p.id,
39
+ description: `AIReady analysis tool: ${p.id}`,
40
+ inputSchema: {
41
+ type: "object",
42
+ properties: {
43
+ path: {
44
+ type: "string",
45
+ description: "Path to the directory to analyze"
46
+ }
47
+ // Future: expose tool-specific options
48
+ },
49
+ required: ["path"]
50
+ }
51
+ }))
52
+ };
53
+ });
54
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
55
+ const { name, arguments: args } = request.params;
56
+ try {
57
+ const provider = ToolRegistry.find(name);
58
+ if (!provider) {
59
+ throw new Error(`Tool ${name} not found`);
60
+ }
61
+ if (!args || typeof args.path !== "string") {
62
+ throw new Error("Missing required argument: path");
63
+ }
64
+ console.error(chalk.blue(`[MCP] Executing ${name} on ${args.path}`));
65
+ const results = await provider.analyze({
66
+ rootDir: args.path
67
+ });
68
+ return {
69
+ content: [
70
+ {
71
+ type: "text",
72
+ text: JSON.stringify(results, null, 2)
73
+ }
74
+ ]
75
+ };
76
+ } catch (error) {
77
+ return {
78
+ content: [
79
+ {
80
+ type: "text",
81
+ text: `Error: ${error.message}`
82
+ }
83
+ ],
84
+ isError: true
85
+ };
86
+ }
87
+ });
88
+ }
89
+ async run() {
90
+ const transport = new StdioServerTransport();
91
+ await this.server.connect(transport);
92
+ console.error(chalk.green("AIReady MCP Server started"));
93
+ }
94
+ };
95
+ var server = new AIReadyMcpServer();
96
+ server.run().catch((error) => {
97
+ console.error(chalk.red("Fatal error starting AIReady MCP Server:"), error);
98
+ process.exit(1);
99
+ });
100
+ export {
101
+ AIReadyMcpServer
102
+ };
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@aiready/mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "AIReady Model Context Protocol (MCP) Server",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "type": "module",
9
+ "bin": {
10
+ "aiready-mcp": "./dist/index.js"
11
+ },
12
+ "dependencies": {
13
+ "@modelcontextprotocol/sdk": "^0.6.0",
14
+ "chalk": "^5.3.0",
15
+ "zod": "^4.3.6",
16
+ "@aiready/core": "0.23.2",
17
+ "@aiready/context-analyzer": "0.21.6",
18
+ "@aiready/consistency": "0.20.2",
19
+ "@aiready/pattern-detect": "0.16.2"
20
+ },
21
+ "devDependencies": {
22
+ "@types/node": "^24.0.0",
23
+ "tsup": "^8.3.5",
24
+ "typescript": "^5.9.3",
25
+ "vitest": "^2.1.0"
26
+ },
27
+ "keywords": [
28
+ "aiready",
29
+ "mcp",
30
+ "model-context-protocol",
31
+ "ai-readiness",
32
+ "code-analysis"
33
+ ],
34
+ "license": "MIT",
35
+ "scripts": {
36
+ "build": "tsup src/index.ts --format esm --clean --dts",
37
+ "dev": "tsup src/index.ts --format esm --watch",
38
+ "test": "vitest run",
39
+ "lint": "eslint src",
40
+ "clean": "rm -rf dist",
41
+ "start": "node dist/index.js"
42
+ }
43
+ }
@@ -0,0 +1,106 @@
1
+ import { describe, it, expect, beforeAll, afterAll } from 'vitest';
2
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
3
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
4
+ import {
5
+ ListToolsRequestSchema,
6
+ CallToolRequestSchema,
7
+ } from '@modelcontextprotocol/sdk/types.js';
8
+ import path from 'path';
9
+ import { fileURLToPath } from 'url';
10
+
11
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
+ // Point to the built JS to ensure we are testing the actual distribution
13
+ const serverPath = path.resolve(__dirname, '../../dist/index.js');
14
+
15
+ describe('AIReady MCP Server Integration', () => {
16
+ let client: Client;
17
+ let transport: StdioClientTransport;
18
+
19
+ beforeAll(async () => {
20
+ transport = new StdioClientTransport({
21
+ command: 'node',
22
+ args: [serverPath],
23
+ });
24
+
25
+ client = new Client(
26
+ { name: 'test-client', version: '1.0.0' },
27
+ { capabilities: {} }
28
+ );
29
+
30
+ await client.connect(transport);
31
+ });
32
+
33
+ afterAll(async () => {
34
+ // StdioClientTransport doesn't have an explicit close, but we should clear references
35
+ });
36
+
37
+ it('should list available tools', async () => {
38
+ const result = await client.listTools();
39
+
40
+ expect(result.tools).toBeDefined();
41
+ expect(result.tools.length).toBeGreaterThan(0);
42
+
43
+ const toolNames = result.tools.map((t) => t.name);
44
+ expect(toolNames).toContain('pattern-detect');
45
+ expect(toolNames).toContain('context-analyzer');
46
+ expect(toolNames).toContain('naming-consistency');
47
+ });
48
+
49
+ it('should expose correct input schema for tools', async () => {
50
+ const result = await client.listTools();
51
+
52
+ const patternDetect = result.tools.find((t) => t.name === 'pattern-detect');
53
+ expect(patternDetect?.inputSchema).toMatchObject({
54
+ type: 'object',
55
+ properties: {
56
+ path: { type: 'string' },
57
+ },
58
+ required: ['path'],
59
+ });
60
+ });
61
+
62
+ it('should execute pattern-detect and return results', async () => {
63
+ const result = await client.callTool({
64
+ name: 'pattern-detect',
65
+ arguments: {
66
+ path: path.resolve(__dirname, '../../../core'), // Test on core package
67
+ },
68
+ });
69
+
70
+ // Check if result has content
71
+ expect(result.content).toBeDefined();
72
+
73
+ const firstContent = result.content[0];
74
+ expect(firstContent.type).toBe('text');
75
+
76
+ const data = JSON.parse((firstContent as any).text);
77
+ expect(data).toHaveProperty('results');
78
+ expect(data).toHaveProperty('summary');
79
+ }, 20000); // Higher timeout for analysis
80
+
81
+ it('should return error for unknown tool', async () => {
82
+ const result = await client.callTool({
83
+ name: 'non-existent-tool',
84
+ arguments: { path: '.' },
85
+ });
86
+
87
+ expect(result.isError).toBe(true);
88
+ expect((result.content[0] as any).text).toContain(
89
+ 'Tool non-existent-tool not found'
90
+ );
91
+ });
92
+
93
+ it('should return error for missing arguments', async () => {
94
+ // Note: The server handles missing arguments and returns isError: true
95
+ const result = await client.callTool({
96
+ name: 'pattern-detect',
97
+ arguments: {},
98
+ });
99
+
100
+ expect(result.isError).toBe(true);
101
+ expect(result.content[0].type).toBe('text');
102
+ expect((result.content[0] as any).text).toContain(
103
+ 'Missing required argument: path'
104
+ );
105
+ });
106
+ });
package/src/index.ts ADDED
@@ -0,0 +1,122 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import {
4
+ CallToolRequestSchema,
5
+ ListToolsRequestSchema,
6
+ } from '@modelcontextprotocol/sdk/types.js';
7
+ import { ToolRegistry, ToolName } from '@aiready/core';
8
+ import chalk from 'chalk';
9
+
10
+ // Pre-load essential tools (following CLI pattern)
11
+ // In a real implementation, we would want to dynamically load these
12
+ // or have them as peer dependencies.
13
+ import '@aiready/pattern-detect';
14
+ import '@aiready/context-analyzer';
15
+ import '@aiready/consistency';
16
+
17
+ /**
18
+ * AIReady MCP Server Implementation
19
+ */
20
+ export class AIReadyMcpServer {
21
+ private server: Server;
22
+
23
+ constructor() {
24
+ this.server = new Server(
25
+ {
26
+ name: 'aiready-server',
27
+ version: '0.1.0',
28
+ },
29
+ {
30
+ capabilities: {
31
+ tools: {},
32
+ },
33
+ }
34
+ );
35
+
36
+ this.setupHandlers();
37
+
38
+ this.server.onerror = (error) => {
39
+ console.error(chalk.red('[MCP Error]'), error);
40
+ };
41
+ }
42
+
43
+ private setupHandlers() {
44
+ // List available tools
45
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => {
46
+ const providers = ToolRegistry.getAll();
47
+
48
+ return {
49
+ tools: providers.map((p) => ({
50
+ name: p.id,
51
+ description: `AIReady analysis tool: ${p.id}`,
52
+ inputSchema: {
53
+ type: 'object',
54
+ properties: {
55
+ path: {
56
+ type: 'string',
57
+ description: 'Path to the directory to analyze',
58
+ },
59
+ // Future: expose tool-specific options
60
+ },
61
+ required: ['path'],
62
+ },
63
+ })),
64
+ };
65
+ });
66
+
67
+ // Handle tool execution
68
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
69
+ const { name, arguments: args } = request.params;
70
+
71
+ try {
72
+ const provider = ToolRegistry.find(name);
73
+ if (!provider) {
74
+ throw new Error(`Tool ${name} not found`);
75
+ }
76
+
77
+ if (!args || typeof args.path !== 'string') {
78
+ throw new Error('Missing required argument: path');
79
+ }
80
+
81
+ console.error(chalk.blue(`[MCP] Executing ${name} on ${args.path}`));
82
+
83
+ const results = await provider.analyze({
84
+ rootDir: args.path,
85
+ });
86
+
87
+ // Format results for the agent
88
+ return {
89
+ content: [
90
+ {
91
+ type: 'text',
92
+ text: JSON.stringify(results, null, 2),
93
+ },
94
+ ],
95
+ };
96
+ } catch (error: any) {
97
+ return {
98
+ content: [
99
+ {
100
+ type: 'text',
101
+ text: `Error: ${error.message}`,
102
+ },
103
+ ],
104
+ isError: true,
105
+ };
106
+ }
107
+ });
108
+ }
109
+
110
+ async run() {
111
+ const transport = new StdioServerTransport();
112
+ await this.server.connect(transport);
113
+ console.error(chalk.green('AIReady MCP Server started'));
114
+ }
115
+ }
116
+
117
+ // Bootstrap the server
118
+ const server = new AIReadyMcpServer();
119
+ server.run().catch((error) => {
120
+ console.error(chalk.red('Fatal error starting AIReady MCP Server:'), error);
121
+ process.exit(1);
122
+ });
package/test-mcp.ts ADDED
@@ -0,0 +1,84 @@
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
3
+ import {
4
+ ListToolsRequestSchema,
5
+ CallToolRequestSchema,
6
+ } from '@modelcontextprotocol/sdk/types.js';
7
+ import path from 'path';
8
+ import { fileURLToPath } from 'url';
9
+
10
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
+ const serverPath = path.join(__dirname, 'dist', 'index.js');
12
+
13
+ async function testServer() {
14
+ console.log('🚀 Starting MCP Server verification test...');
15
+
16
+ const transport = new StdioClientTransport({
17
+ command: 'node',
18
+ args: [serverPath],
19
+ env: {
20
+ ...process.env,
21
+ NODE_ENV: 'test',
22
+ },
23
+ });
24
+
25
+ const client = new Client(
26
+ {
27
+ name: 'test-client',
28
+ version: '1.0.0',
29
+ },
30
+ {
31
+ capabilities: {},
32
+ }
33
+ );
34
+
35
+ try {
36
+ await client.connect(transport);
37
+ console.log('✅ Connected to MCP Server');
38
+
39
+ // Test ListTools
40
+ const tools = await client.request(
41
+ { method: 'tools/list' },
42
+ ListToolsRequestSchema
43
+ );
44
+ console.log(
45
+ '📋 Available Tools:',
46
+ tools.tools.map((t) => t.name).join(', ')
47
+ );
48
+
49
+ if (tools.tools.length === 0) {
50
+ throw new Error('No tools listed!');
51
+ }
52
+
53
+ // Test CallTool (pattern-detect)
54
+ console.log("🔍 Testing 'pattern-detect'...");
55
+ const rootDir = '/Users/pengcao/projects/aiready'; // Test on current repo
56
+ const result = await client.request(
57
+ {
58
+ method: 'tools/call',
59
+ params: {
60
+ name: 'pattern-detect',
61
+ arguments: { path: rootDir },
62
+ },
63
+ },
64
+ CallToolRequestSchema
65
+ );
66
+
67
+ if (result.isError) {
68
+ console.error('❌ Tool execution failed:', result.content[0].text);
69
+ } else {
70
+ console.log('✅ Tool execution success!');
71
+ const data = JSON.parse(result.content[0].text);
72
+ console.log(
73
+ `📊 Found ${data.duplicates?.length || 0} duplicate patterns.`
74
+ );
75
+ }
76
+ } catch (error) {
77
+ console.error('💥 Test failed:', error);
78
+ } finally {
79
+ console.log('🏁 Verification test complete.');
80
+ process.exit(0);
81
+ }
82
+ }
83
+
84
+ testServer();
package/tsconfig.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "../../tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "dist",
5
+ "rootDir": "src"
6
+ },
7
+ "include": ["src/**/*"]
8
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { defineConfig } from 'tsup';
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.ts'],
5
+ format: ['esm'],
6
+ dts: true,
7
+ clean: true,
8
+ shims: true,
9
+ // Treat these as external to avoid bundling them (they will be resolved at runtime)
10
+ external: [
11
+ '@aiready/core',
12
+ '@aiready/pattern-detect',
13
+ '@aiready/context-analyzer',
14
+ '@aiready/consistency',
15
+ '@modelcontextprotocol/sdk',
16
+ 'path',
17
+ 'url',
18
+ 'fs',
19
+ ],
20
+ // Ensure we are targeting a modern node version
21
+ target: 'node20',
22
+ // Build to be executable
23
+ banner: {
24
+ js: '#!/usr/bin/env node',
25
+ },
26
+ });