@nebutra/mcp 0.1.2 → 0.1.4

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.
@@ -1,211 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import fs from "node:fs";
4
- import path from "node:path";
5
- import { Server } from "@modelcontextprotocol/sdk/server/index.js";
6
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
7
- import {
8
- CallToolRequestSchema,
9
- ListResourcesRequestSchema,
10
- ListToolsRequestSchema,
11
- ReadResourceRequestSchema,
12
- } from "@modelcontextprotocol/sdk/types.js";
13
-
14
- /**
15
- * Nebutra MCP Context Server
16
- * Exposes core project files and state to Cursor / Windsurf allowing AI Agents
17
- * to instantly understand the Nebutra-Sailor application structure and routing logic.
18
- */
19
- class NebutraContextServer {
20
- private server: Server;
21
- private projectRoot: string;
22
-
23
- constructor(projectRoot?: string) {
24
- this.projectRoot = projectRoot || process.cwd();
25
-
26
- this.server = new Server(
27
- {
28
- name: "@nebutra/context-server",
29
- version: "0.1.0",
30
- },
31
- {
32
- capabilities: {
33
- resources: {},
34
- tools: {},
35
- },
36
- },
37
- );
38
-
39
- this.setupResourceHandlers();
40
- this.setupToolHandlers();
41
-
42
- this.server.onerror = (_error) => {};
43
- }
44
-
45
- private setupResourceHandlers() {
46
- const handlers = createContextServerHandlers(this.projectRoot);
47
-
48
- this.server.setRequestHandler(ListResourcesRequestSchema, async () => handlers.listResources());
49
-
50
- this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
51
- return handlers.readResource(request.params);
52
- });
53
- }
54
-
55
- private setupToolHandlers() {
56
- const handlers = createContextServerHandlers(this.projectRoot);
57
-
58
- this.server.setRequestHandler(ListToolsRequestSchema, async () => handlers.listTools());
59
-
60
- this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
61
- return handlers.callTool(request.params);
62
- });
63
- }
64
-
65
- async run() {
66
- const transport = new StdioServerTransport();
67
- await this.server.connect(transport);
68
- }
69
- }
70
-
71
- const RESOURCE_MAP = {
72
- "file:///nebutra.config.json": {
73
- relativePath: "nebutra.config.json",
74
- name: "Nebutra Configuration",
75
- mimeType: "application/json",
76
- description:
77
- "Global configurations for the Nebutra template including enabled features (auth, payments, i18n, db).",
78
- },
79
- "file:///prisma/schema.prisma": {
80
- relativePath: "packages/platform/db/prisma/schema.prisma",
81
- name: "Database Schema Overview",
82
- mimeType: "text/plain",
83
- description: "The core Prisma schema defining the database tables and relationships.",
84
- },
85
- } as const;
86
-
87
- export function createContextServerHandlers(projectRoot: string) {
88
- return {
89
- async listResources() {
90
- return {
91
- resources: Object.entries(RESOURCE_MAP).map(([uri, resource]) => ({
92
- uri,
93
- name: resource.name,
94
- mimeType: resource.mimeType,
95
- description: resource.description,
96
- })),
97
- };
98
- },
99
-
100
- async readResource({ uri }: { uri: string }) {
101
- const resource = RESOURCE_MAP[uri as keyof typeof RESOURCE_MAP];
102
- if (!resource) {
103
- throw new Error(`Resource not found: ${uri}`);
104
- }
105
-
106
- const filePath = path.join(projectRoot, resource.relativePath);
107
- try {
108
- const content = fs.readFileSync(filePath, "utf-8");
109
- return {
110
- contents: [
111
- {
112
- uri,
113
- mimeType: resource.mimeType,
114
- text: content,
115
- },
116
- ],
117
- };
118
- } catch {
119
- throw new Error(`Failed to read the requested resource file at ${filePath}`);
120
- }
121
- },
122
-
123
- async listTools() {
124
- return {
125
- tools: [
126
- {
127
- name: "get_project_structure",
128
- description: "Returns a bounded app/package routing tree for the current project.",
129
- inputSchema: {
130
- type: "object",
131
- properties: {},
132
- required: [],
133
- },
134
- },
135
- ],
136
- };
137
- },
138
-
139
- async callTool({ name }: { name: string; arguments?: Record<string, unknown> | undefined }) {
140
- if (name !== "get_project_structure") {
141
- throw new Error(`Unknown tool: ${name}`);
142
- }
143
-
144
- try {
145
- return {
146
- content: [
147
- {
148
- type: "text",
149
- text: getProjectStructure(projectRoot),
150
- },
151
- ],
152
- };
153
- } catch (error) {
154
- return {
155
- content: [
156
- {
157
- type: "text",
158
- text: `Error: ${error instanceof Error ? error.message : String(error)}`,
159
- },
160
- ],
161
- isError: true,
162
- };
163
- }
164
- },
165
- };
166
- }
167
-
168
- function getProjectStructure(projectRoot: string): string {
169
- const roots = ["apps", "packages", "backends"].filter((segment) =>
170
- fs.existsSync(path.join(projectRoot, segment)),
171
- );
172
- if (roots.length === 0) return "No Nebutra workspace roots found.";
173
-
174
- const entries: string[] = [];
175
- for (const root of roots) {
176
- walkProjectTree(path.join(projectRoot, root), root, entries, 4);
177
- }
178
- return entries.length > 0 ? entries.join("\n") : "No project entries found.";
179
- }
180
-
181
- function walkProjectTree(
182
- absoluteDir: string,
183
- relativeDir: string,
184
- entries: string[],
185
- depthRemaining: number,
186
- ): void {
187
- if (depthRemaining < 0 || entries.length >= 200) return;
188
-
189
- entries.push(relativeDir);
190
-
191
- for (const dirent of fs.readdirSync(absoluteDir, { withFileTypes: true })) {
192
- if (!dirent.isDirectory()) continue;
193
- if (dirent.name === "node_modules" || dirent.name.startsWith(".")) continue;
194
- walkProjectTree(
195
- path.join(absoluteDir, dirent.name),
196
- path.join(relativeDir, dirent.name),
197
- entries,
198
- depthRemaining - 1,
199
- );
200
- }
201
- }
202
-
203
- // Export a factory or run directly if invoked as script
204
- export const startContextServer = () => {
205
- const server = new NebutraContextServer();
206
- server.run().catch(console.error);
207
- };
208
-
209
- if (process.argv[1]?.endsWith("contextServer.js") || process.argv[1]?.endsWith("nebutra-mcp")) {
210
- startContextServer();
211
- }
@@ -1,5 +0,0 @@
1
- export {
2
- getInternalServerIds,
3
- INTERNAL_SERVERS,
4
- registerInternalServers,
5
- } from "./internalServers";
@@ -1,70 +0,0 @@
1
- import { serverRegistry } from "../registry/serverRegistry";
2
- import type { MCPServerConfig } from "../types";
3
-
4
- /**
5
- * Register internal Nebutra services as MCP servers
6
- * These wrap our existing microservices with MCP-compatible interfaces
7
- */
8
-
9
- export const INTERNAL_SERVERS: MCPServerConfig[] = [
10
- // AI Service
11
- {
12
- id: "nebutra-ai",
13
- name: "Nebutra AI Service",
14
- description: "AI-powered text generation, embedding, and translation",
15
- endpoint: process.env.AI_SERVICE_URL || "http://localhost:8001",
16
- transport: "http",
17
- tools: [
18
- {
19
- name: "generate_text",
20
- description: "Generate text using LLM",
21
- parameters: {
22
- prompt: { type: "string", description: "Input prompt", required: true },
23
- max_tokens: { type: "number", description: "Max tokens to generate", default: 1000 },
24
- temperature: { type: "number", description: "Sampling temperature", default: 0.7 },
25
- },
26
- returns: "Generated text",
27
- },
28
- {
29
- name: "create_embedding",
30
- description: "Create vector embedding for text",
31
- parameters: {
32
- text: { type: "string", description: "Text to embed", required: true },
33
- model: {
34
- type: "string",
35
- description: "Embedding model",
36
- default: "text-embedding-3-small",
37
- },
38
- },
39
- returns: "Vector embedding array",
40
- },
41
- {
42
- name: "translate",
43
- description: "Translate text between languages",
44
- parameters: {
45
- text: { type: "string", description: "Text to translate", required: true },
46
- source: { type: "string", description: "Source language code", default: "en" },
47
- target: { type: "string", description: "Target language code", required: true },
48
- },
49
- returns: "Translated text",
50
- },
51
- ],
52
- rateLimit: { maxRequests: 100, windowMs: 60000 },
53
- },
54
- ];
55
-
56
- /**
57
- * Register all internal servers
58
- */
59
- export function registerInternalServers(): void {
60
- for (const server of INTERNAL_SERVERS) {
61
- serverRegistry.register(server);
62
- }
63
- }
64
-
65
- /**
66
- * Get list of internal server IDs
67
- */
68
- export function getInternalServerIds(): string[] {
69
- return INTERNAL_SERVERS.map((s) => s.id);
70
- }
package/src/types.ts DELETED
@@ -1,135 +0,0 @@
1
- import { z } from "zod";
2
-
3
- // ============================================
4
- // MCP Tool Definition
5
- // ============================================
6
-
7
- export const ToolParameterSchema = z.object({
8
- type: z.enum(["string", "number", "boolean", "object", "array"]),
9
- description: z.string().optional(),
10
- required: z.boolean().optional(),
11
- default: z.any().optional(),
12
- });
13
-
14
- export const ToolDefinitionSchema = z.object({
15
- name: z.string(),
16
- description: z.string(),
17
- parameters: z.record(z.string(), ToolParameterSchema).optional(),
18
- returns: z.string().optional(),
19
- allowedPlans: z.array(z.string()).optional(),
20
- allowedTenants: z.array(z.string()).optional(),
21
- requiredPermissions: z.array(z.string()).optional(),
22
- });
23
-
24
- export type ToolParameter = z.infer<typeof ToolParameterSchema>;
25
- export type ToolDefinition = z.infer<typeof ToolDefinitionSchema>;
26
-
27
- // ============================================
28
- // MCP Request/Response
29
- // ============================================
30
-
31
- export interface MCPRequest {
32
- id: string;
33
- method: string;
34
- params?: Record<string, unknown>;
35
- }
36
-
37
- export interface MCPResponse {
38
- id: string;
39
- result?: unknown;
40
- error?: MCPError;
41
- }
42
-
43
- export interface MCPError {
44
- code: number;
45
- message: string;
46
- data?: unknown;
47
- }
48
-
49
- // ============================================
50
- // MCP Context (with tenant info)
51
- // ============================================
52
-
53
- export interface MCPContext {
54
- requestId: string;
55
- tenantId?: string;
56
- userId?: string;
57
- plan?: string;
58
- permissions?: string[];
59
- metadata?: Record<string, unknown>;
60
- }
61
-
62
- // ============================================
63
- // Tool Execution
64
- // ============================================
65
-
66
- export interface ToolExecutionRequest {
67
- tool: string;
68
- arguments: Record<string, unknown>;
69
- context: MCPContext;
70
- }
71
-
72
- export interface ToolExecutionResult {
73
- success: boolean;
74
- result?: unknown;
75
- error?: string;
76
- duration: number;
77
- tokensUsed?: number;
78
- }
79
-
80
- export interface MCPServerManifest {
81
- name: string;
82
- version: string;
83
- scopes: string[];
84
- homepage?: string;
85
- }
86
-
87
- // ============================================
88
- // MCP Server Registration
89
- // ============================================
90
-
91
- export interface MCPServerConfig {
92
- id: string;
93
- name: string;
94
- description: string;
95
- endpoint: string;
96
- transport: "http" | "websocket" | "stdio" | "local";
97
- manifest?: MCPServerManifest;
98
- tools: ToolDefinition[];
99
- handlers?: Record<string, MCPToolHandler>;
100
- authentication?: {
101
- type: "bearer" | "api-key" | "none";
102
- headerName?: string;
103
- };
104
- rateLimit?: {
105
- maxRequests: number;
106
- windowMs: number;
107
- };
108
- // Tenant access control
109
- allowedPlans?: string[]; // e.g., ["PRO", "ENTERPRISE"]
110
- allowedTenants?: string[]; // specific tenant IDs
111
- }
112
-
113
- export type MCPToolHandler = (
114
- args: Record<string, unknown>,
115
- context: MCPContext,
116
- ) => unknown | Promise<unknown>;
117
-
118
- // ============================================
119
- // Smithery Integration
120
- // ============================================
121
-
122
- export interface SmitheryServerInfo {
123
- qualifiedName: string;
124
- displayName: string;
125
- description: string;
126
- homepage?: string;
127
- useCount?: number;
128
- isDeployed?: boolean;
129
- }
130
-
131
- export interface SmitheryConfig {
132
- apiKey?: string;
133
- baseUrl: string;
134
- defaultServers?: string[]; // Pre-configured server qualified names
135
- }
package/tsconfig.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "../../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "outDir": "dist",
5
- "rootDir": "src"
6
- },
7
- "include": ["src/**/*"],
8
- "exclude": ["node_modules", "dist"]
9
- }
package/tsup.config.ts DELETED
@@ -1,17 +0,0 @@
1
- import { defineConfig } from "tsup";
2
-
3
- export default defineConfig({
4
- entry: ["src/index.ts", "src/cli.ts", "src/server/contextServer.ts"],
5
- format: ["esm"],
6
- dts: true,
7
- clean: true,
8
- target: "node18",
9
- outDir: "dist",
10
- minify: false,
11
- external: [
12
- "@modelcontextprotocol/sdk",
13
- "@nebutra/errors",
14
- "@nebutra/event-log",
15
- "@nebutra/trace-store",
16
- ],
17
- });