@nebutra/mcp 0.1.0 → 0.1.1
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/.turbo/turbo-build.log +22 -0
- package/.turbo/turbo-test.log +14 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/CHANGELOG.md +15 -0
- package/dist/chunk-ORGYGQJV.js +711 -0
- package/dist/chunk-YMTQFRV2.js +178 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +55 -0
- package/dist/index.d.ts +378 -0
- package/dist/index.js +44 -0
- package/dist/server/contextServer.d.ts +50 -0
- package/dist/server/contextServer.js +8 -0
- package/examples/doctor.ts +14 -0
- package/examples/local-consent.ts +30 -0
- package/examples/read-debug.ts +5 -0
- package/package.json +12 -7
- package/src/__tests__/registry-and-context.test.ts +234 -0
- package/src/cli.ts +47 -0
- package/src/client/mcpClient.ts +26 -5
- package/src/consent.ts +46 -0
- package/src/debug.ts +43 -0
- package/src/host.ts +314 -0
- package/src/index.ts +7 -0
- package/src/registry/serverRegistry.ts +38 -1
- package/src/server/contextServer.ts +130 -57
- package/src/types.ts +18 -1
- package/tsup.config.ts +7 -1
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// src/server/contextServer.ts
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
5
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
+
import {
|
|
7
|
+
CallToolRequestSchema,
|
|
8
|
+
ListResourcesRequestSchema,
|
|
9
|
+
ListToolsRequestSchema,
|
|
10
|
+
ReadResourceRequestSchema
|
|
11
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
12
|
+
var NebutraContextServer = class {
|
|
13
|
+
server;
|
|
14
|
+
projectRoot;
|
|
15
|
+
constructor(projectRoot) {
|
|
16
|
+
this.projectRoot = projectRoot || process.cwd();
|
|
17
|
+
this.server = new Server(
|
|
18
|
+
{
|
|
19
|
+
name: "@nebutra/context-server",
|
|
20
|
+
version: "0.1.0"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
capabilities: {
|
|
24
|
+
resources: {},
|
|
25
|
+
tools: {}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
this.setupResourceHandlers();
|
|
30
|
+
this.setupToolHandlers();
|
|
31
|
+
this.server.onerror = (_error) => {
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
setupResourceHandlers() {
|
|
35
|
+
const handlers = createContextServerHandlers(this.projectRoot);
|
|
36
|
+
this.server.setRequestHandler(ListResourcesRequestSchema, async () => handlers.listResources());
|
|
37
|
+
this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
38
|
+
return handlers.readResource(request.params);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
setupToolHandlers() {
|
|
42
|
+
const handlers = createContextServerHandlers(this.projectRoot);
|
|
43
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => handlers.listTools());
|
|
44
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
45
|
+
return handlers.callTool(request.params);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async run() {
|
|
49
|
+
const transport = new StdioServerTransport();
|
|
50
|
+
await this.server.connect(transport);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
var RESOURCE_MAP = {
|
|
54
|
+
"file:///nebutra.config.json": {
|
|
55
|
+
relativePath: "nebutra.config.json",
|
|
56
|
+
name: "Nebutra Configuration",
|
|
57
|
+
mimeType: "application/json",
|
|
58
|
+
description: "Global configurations for the Nebutra template including enabled features (auth, payments, i18n, db)."
|
|
59
|
+
},
|
|
60
|
+
"file:///prisma/schema.prisma": {
|
|
61
|
+
relativePath: "packages/platform/db/prisma/schema.prisma",
|
|
62
|
+
name: "Database Schema Overview",
|
|
63
|
+
mimeType: "text/plain",
|
|
64
|
+
description: "The core Prisma schema defining the database tables and relationships."
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
function createContextServerHandlers(projectRoot) {
|
|
68
|
+
return {
|
|
69
|
+
async listResources() {
|
|
70
|
+
return {
|
|
71
|
+
resources: Object.entries(RESOURCE_MAP).map(([uri, resource]) => ({
|
|
72
|
+
uri,
|
|
73
|
+
name: resource.name,
|
|
74
|
+
mimeType: resource.mimeType,
|
|
75
|
+
description: resource.description
|
|
76
|
+
}))
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
async readResource({ uri }) {
|
|
80
|
+
const resource = RESOURCE_MAP[uri];
|
|
81
|
+
if (!resource) {
|
|
82
|
+
throw new Error(`Resource not found: ${uri}`);
|
|
83
|
+
}
|
|
84
|
+
const filePath = path.join(projectRoot, resource.relativePath);
|
|
85
|
+
try {
|
|
86
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
87
|
+
return {
|
|
88
|
+
contents: [
|
|
89
|
+
{
|
|
90
|
+
uri,
|
|
91
|
+
mimeType: resource.mimeType,
|
|
92
|
+
text: content
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
};
|
|
96
|
+
} catch {
|
|
97
|
+
throw new Error(`Failed to read the requested resource file at ${filePath}`);
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
async listTools() {
|
|
101
|
+
return {
|
|
102
|
+
tools: [
|
|
103
|
+
{
|
|
104
|
+
name: "get_project_structure",
|
|
105
|
+
description: "Returns a bounded app/package routing tree for the current project.",
|
|
106
|
+
inputSchema: {
|
|
107
|
+
type: "object",
|
|
108
|
+
properties: {},
|
|
109
|
+
required: []
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
};
|
|
114
|
+
},
|
|
115
|
+
async callTool({ name }) {
|
|
116
|
+
if (name !== "get_project_structure") {
|
|
117
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
return {
|
|
121
|
+
content: [
|
|
122
|
+
{
|
|
123
|
+
type: "text",
|
|
124
|
+
text: getProjectStructure(projectRoot)
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
};
|
|
128
|
+
} catch (error) {
|
|
129
|
+
return {
|
|
130
|
+
content: [
|
|
131
|
+
{
|
|
132
|
+
type: "text",
|
|
133
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`
|
|
134
|
+
}
|
|
135
|
+
],
|
|
136
|
+
isError: true
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function getProjectStructure(projectRoot) {
|
|
143
|
+
const roots = ["apps", "packages", "backends"].filter(
|
|
144
|
+
(segment) => fs.existsSync(path.join(projectRoot, segment))
|
|
145
|
+
);
|
|
146
|
+
if (roots.length === 0) return "No Nebutra workspace roots found.";
|
|
147
|
+
const entries = [];
|
|
148
|
+
for (const root of roots) {
|
|
149
|
+
walkProjectTree(path.join(projectRoot, root), root, entries, 4);
|
|
150
|
+
}
|
|
151
|
+
return entries.length > 0 ? entries.join("\n") : "No project entries found.";
|
|
152
|
+
}
|
|
153
|
+
function walkProjectTree(absoluteDir, relativeDir, entries, depthRemaining) {
|
|
154
|
+
if (depthRemaining < 0 || entries.length >= 200) return;
|
|
155
|
+
entries.push(relativeDir);
|
|
156
|
+
for (const dirent of fs.readdirSync(absoluteDir, { withFileTypes: true })) {
|
|
157
|
+
if (!dirent.isDirectory()) continue;
|
|
158
|
+
if (dirent.name === "node_modules" || dirent.name.startsWith(".")) continue;
|
|
159
|
+
walkProjectTree(
|
|
160
|
+
path.join(absoluteDir, dirent.name),
|
|
161
|
+
path.join(relativeDir, dirent.name),
|
|
162
|
+
entries,
|
|
163
|
+
depthRemaining - 1
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
var startContextServer = () => {
|
|
168
|
+
const server = new NebutraContextServer();
|
|
169
|
+
server.run().catch(console.error);
|
|
170
|
+
};
|
|
171
|
+
if (process.argv[1]?.endsWith("contextServer.js") || process.argv[1]?.endsWith("nebutra-mcp")) {
|
|
172
|
+
startContextServer();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export {
|
|
176
|
+
createContextServerHandlers,
|
|
177
|
+
startContextServer
|
|
178
|
+
};
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
McpHost,
|
|
3
|
+
readToolDebug
|
|
4
|
+
} from "./chunk-ORGYGQJV.js";
|
|
5
|
+
import {
|
|
6
|
+
createContextServerHandlers
|
|
7
|
+
} from "./chunk-YMTQFRV2.js";
|
|
8
|
+
|
|
9
|
+
// src/cli.ts
|
|
10
|
+
var command = process.argv[2] ?? "doctor";
|
|
11
|
+
var host = new McpHost();
|
|
12
|
+
var contextHandlers = createContextServerHandlers(process.cwd());
|
|
13
|
+
host.connectLocal({
|
|
14
|
+
id: "nebutra-context",
|
|
15
|
+
name: "Nebutra Context",
|
|
16
|
+
description: "Read-only project context tools",
|
|
17
|
+
manifest: {
|
|
18
|
+
name: "nebutra-context",
|
|
19
|
+
version: "1.0.0",
|
|
20
|
+
scopes: ["project:read"]
|
|
21
|
+
},
|
|
22
|
+
tools: [
|
|
23
|
+
{
|
|
24
|
+
name: "get_project_structure",
|
|
25
|
+
description: "Returns a bounded app/package routing tree for the current project.",
|
|
26
|
+
parameters: {}
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
handlers: {
|
|
30
|
+
get_project_structure: async () => contextHandlers.callTool({ name: "get_project_structure" })
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
if (command === "doctor") {
|
|
34
|
+
process.stdout.write(
|
|
35
|
+
`${JSON.stringify({ capability: "tool-protocol", ...await host.doctor() }, null, 2)}
|
|
36
|
+
`
|
|
37
|
+
);
|
|
38
|
+
} else if (command === "debug") {
|
|
39
|
+
const id = process.argv[3];
|
|
40
|
+
const entries = await readToolDebug(id ? 50 : 10);
|
|
41
|
+
process.stdout.write(
|
|
42
|
+
`${JSON.stringify({ capability: "tool-protocol", id, entries }, null, 2)}
|
|
43
|
+
`
|
|
44
|
+
);
|
|
45
|
+
} else if (command === "inspect") {
|
|
46
|
+
const serverId = process.argv[3] ?? "nebutra-context";
|
|
47
|
+
process.stdout.write(
|
|
48
|
+
`${JSON.stringify({ capability: "tool-protocol", server: host.inspect(serverId) }, null, 2)}
|
|
49
|
+
`
|
|
50
|
+
);
|
|
51
|
+
} else {
|
|
52
|
+
process.stderr.write(`Unknown tool-protocol command: ${command}
|
|
53
|
+
`);
|
|
54
|
+
process.exitCode = 1;
|
|
55
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { EventLog } from '@nebutra/event-log';
|
|
3
|
+
import { TraceStore } from '@nebutra/trace-store';
|
|
4
|
+
|
|
5
|
+
declare const ToolParameterSchema: z.ZodObject<{
|
|
6
|
+
type: z.ZodEnum<{
|
|
7
|
+
string: "string";
|
|
8
|
+
number: "number";
|
|
9
|
+
boolean: "boolean";
|
|
10
|
+
object: "object";
|
|
11
|
+
array: "array";
|
|
12
|
+
}>;
|
|
13
|
+
description: z.ZodOptional<z.ZodString>;
|
|
14
|
+
required: z.ZodOptional<z.ZodBoolean>;
|
|
15
|
+
default: z.ZodOptional<z.ZodAny>;
|
|
16
|
+
}, z.core.$strip>;
|
|
17
|
+
declare const ToolDefinitionSchema: z.ZodObject<{
|
|
18
|
+
name: z.ZodString;
|
|
19
|
+
description: z.ZodString;
|
|
20
|
+
parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
21
|
+
type: z.ZodEnum<{
|
|
22
|
+
string: "string";
|
|
23
|
+
number: "number";
|
|
24
|
+
boolean: "boolean";
|
|
25
|
+
object: "object";
|
|
26
|
+
array: "array";
|
|
27
|
+
}>;
|
|
28
|
+
description: z.ZodOptional<z.ZodString>;
|
|
29
|
+
required: z.ZodOptional<z.ZodBoolean>;
|
|
30
|
+
default: z.ZodOptional<z.ZodAny>;
|
|
31
|
+
}, z.core.$strip>>>;
|
|
32
|
+
returns: z.ZodOptional<z.ZodString>;
|
|
33
|
+
allowedPlans: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
34
|
+
allowedTenants: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
35
|
+
requiredPermissions: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
36
|
+
}, z.core.$strip>;
|
|
37
|
+
type ToolParameter = z.infer<typeof ToolParameterSchema>;
|
|
38
|
+
type ToolDefinition = z.infer<typeof ToolDefinitionSchema>;
|
|
39
|
+
interface MCPRequest {
|
|
40
|
+
id: string;
|
|
41
|
+
method: string;
|
|
42
|
+
params?: Record<string, unknown>;
|
|
43
|
+
}
|
|
44
|
+
interface MCPResponse {
|
|
45
|
+
id: string;
|
|
46
|
+
result?: unknown;
|
|
47
|
+
error?: MCPError;
|
|
48
|
+
}
|
|
49
|
+
interface MCPError {
|
|
50
|
+
code: number;
|
|
51
|
+
message: string;
|
|
52
|
+
data?: unknown;
|
|
53
|
+
}
|
|
54
|
+
interface MCPContext {
|
|
55
|
+
requestId: string;
|
|
56
|
+
tenantId?: string;
|
|
57
|
+
userId?: string;
|
|
58
|
+
plan?: string;
|
|
59
|
+
permissions?: string[];
|
|
60
|
+
metadata?: Record<string, unknown>;
|
|
61
|
+
}
|
|
62
|
+
interface ToolExecutionRequest {
|
|
63
|
+
tool: string;
|
|
64
|
+
arguments: Record<string, unknown>;
|
|
65
|
+
context: MCPContext;
|
|
66
|
+
}
|
|
67
|
+
interface ToolExecutionResult {
|
|
68
|
+
success: boolean;
|
|
69
|
+
result?: unknown;
|
|
70
|
+
error?: string;
|
|
71
|
+
duration: number;
|
|
72
|
+
tokensUsed?: number;
|
|
73
|
+
}
|
|
74
|
+
interface MCPServerManifest {
|
|
75
|
+
name: string;
|
|
76
|
+
version: string;
|
|
77
|
+
scopes: string[];
|
|
78
|
+
homepage?: string;
|
|
79
|
+
}
|
|
80
|
+
interface MCPServerConfig {
|
|
81
|
+
id: string;
|
|
82
|
+
name: string;
|
|
83
|
+
description: string;
|
|
84
|
+
endpoint: string;
|
|
85
|
+
transport: "http" | "websocket" | "stdio" | "local";
|
|
86
|
+
manifest?: MCPServerManifest;
|
|
87
|
+
tools: ToolDefinition[];
|
|
88
|
+
handlers?: Record<string, MCPToolHandler>;
|
|
89
|
+
authentication?: {
|
|
90
|
+
type: "bearer" | "api-key" | "none";
|
|
91
|
+
headerName?: string;
|
|
92
|
+
};
|
|
93
|
+
rateLimit?: {
|
|
94
|
+
maxRequests: number;
|
|
95
|
+
windowMs: number;
|
|
96
|
+
};
|
|
97
|
+
allowedPlans?: string[];
|
|
98
|
+
allowedTenants?: string[];
|
|
99
|
+
}
|
|
100
|
+
type MCPToolHandler = (args: Record<string, unknown>, context: MCPContext) => unknown | Promise<unknown>;
|
|
101
|
+
interface SmitheryServerInfo {
|
|
102
|
+
qualifiedName: string;
|
|
103
|
+
displayName: string;
|
|
104
|
+
description: string;
|
|
105
|
+
homepage?: string;
|
|
106
|
+
useCount?: number;
|
|
107
|
+
isDeployed?: boolean;
|
|
108
|
+
}
|
|
109
|
+
interface SmitheryConfig {
|
|
110
|
+
apiKey?: string;
|
|
111
|
+
baseUrl: string;
|
|
112
|
+
defaultServers?: string[];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Registry for MCP servers and their tools
|
|
117
|
+
* Handles server registration, discovery, and access control
|
|
118
|
+
*/
|
|
119
|
+
declare class MCPServerRegistry {
|
|
120
|
+
private servers;
|
|
121
|
+
private toolIndex;
|
|
122
|
+
/**
|
|
123
|
+
* Register an MCP server
|
|
124
|
+
*/
|
|
125
|
+
register(config: MCPServerConfig): void;
|
|
126
|
+
/**
|
|
127
|
+
* Unregister an MCP server
|
|
128
|
+
*/
|
|
129
|
+
unregister(serverId: string): boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Get server by ID
|
|
132
|
+
*/
|
|
133
|
+
getServer(serverId: string): MCPServerConfig | undefined;
|
|
134
|
+
/**
|
|
135
|
+
* Find server by tool name
|
|
136
|
+
*/
|
|
137
|
+
findServerByTool(toolName: string): MCPServerConfig | undefined;
|
|
138
|
+
/**
|
|
139
|
+
* Get all registered servers
|
|
140
|
+
*/
|
|
141
|
+
getAllServers(): MCPServerConfig[];
|
|
142
|
+
/**
|
|
143
|
+
* Get all available tools
|
|
144
|
+
*/
|
|
145
|
+
getAllTools(): Array<ToolDefinition & {
|
|
146
|
+
serverId: string;
|
|
147
|
+
}>;
|
|
148
|
+
/**
|
|
149
|
+
* Check if a context has access to a server
|
|
150
|
+
*/
|
|
151
|
+
canAccess(serverId: string, context: MCPContext): boolean;
|
|
152
|
+
/**
|
|
153
|
+
* Check whether a context can execute a specific tool. Tool-level policy
|
|
154
|
+
* narrows the server policy and supports tenant, plan, and permission gates.
|
|
155
|
+
*/
|
|
156
|
+
canAccessTool(toolName: string, context: MCPContext): boolean;
|
|
157
|
+
/**
|
|
158
|
+
* Get tools accessible by a context
|
|
159
|
+
*/
|
|
160
|
+
getAccessibleTools(context: MCPContext): Array<ToolDefinition & {
|
|
161
|
+
serverId: string;
|
|
162
|
+
}>;
|
|
163
|
+
private findTool;
|
|
164
|
+
}
|
|
165
|
+
declare const serverRegistry: MCPServerRegistry;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* MCP Client for executing tools across registered servers
|
|
169
|
+
*/
|
|
170
|
+
declare class MCPClient {
|
|
171
|
+
private readonly registry;
|
|
172
|
+
private requestCounter;
|
|
173
|
+
constructor(registry?: MCPServerRegistry);
|
|
174
|
+
/**
|
|
175
|
+
* Execute a tool by name
|
|
176
|
+
*/
|
|
177
|
+
executeTool(toolName: string, args: Record<string, unknown>, context: MCPContext): Promise<ToolExecutionResult>;
|
|
178
|
+
/**
|
|
179
|
+
* Execute tool on a specific server
|
|
180
|
+
*/
|
|
181
|
+
private executeOnServer;
|
|
182
|
+
/**
|
|
183
|
+
* Execute via HTTP transport
|
|
184
|
+
*/
|
|
185
|
+
private executeHttp;
|
|
186
|
+
/**
|
|
187
|
+
* Execute via WebSocket transport
|
|
188
|
+
*/
|
|
189
|
+
private executeWebSocket;
|
|
190
|
+
private executeLocal;
|
|
191
|
+
/**
|
|
192
|
+
* List available tools for a context
|
|
193
|
+
*/
|
|
194
|
+
listTools(context: MCPContext): ({
|
|
195
|
+
name: string;
|
|
196
|
+
description: string;
|
|
197
|
+
parameters?: Record<string, {
|
|
198
|
+
type: "string" | "number" | "boolean" | "object" | "array";
|
|
199
|
+
description?: string | undefined;
|
|
200
|
+
required?: boolean | undefined;
|
|
201
|
+
default?: any;
|
|
202
|
+
}> | undefined;
|
|
203
|
+
returns?: string | undefined;
|
|
204
|
+
allowedPlans?: string[] | undefined;
|
|
205
|
+
allowedTenants?: string[] | undefined;
|
|
206
|
+
requiredPermissions?: string[] | undefined;
|
|
207
|
+
} & {
|
|
208
|
+
serverId: string;
|
|
209
|
+
})[];
|
|
210
|
+
/**
|
|
211
|
+
* Get tool definition
|
|
212
|
+
*/
|
|
213
|
+
getTool(toolName: string, context: MCPContext): {
|
|
214
|
+
name: string;
|
|
215
|
+
description: string;
|
|
216
|
+
parameters?: Record<string, {
|
|
217
|
+
type: "string" | "number" | "boolean" | "object" | "array";
|
|
218
|
+
description?: string | undefined;
|
|
219
|
+
required?: boolean | undefined;
|
|
220
|
+
default?: any;
|
|
221
|
+
}> | undefined;
|
|
222
|
+
returns?: string | undefined;
|
|
223
|
+
allowedPlans?: string[] | undefined;
|
|
224
|
+
allowedTenants?: string[] | undefined;
|
|
225
|
+
requiredPermissions?: string[] | undefined;
|
|
226
|
+
} | undefined;
|
|
227
|
+
}
|
|
228
|
+
declare const mcpClient: MCPClient;
|
|
229
|
+
|
|
230
|
+
interface ToolConsentGrant {
|
|
231
|
+
readonly tenantId: string;
|
|
232
|
+
readonly userId?: string;
|
|
233
|
+
readonly serverId: string;
|
|
234
|
+
readonly toolName: string;
|
|
235
|
+
readonly scopes: readonly string[];
|
|
236
|
+
}
|
|
237
|
+
interface ToolConsentStore {
|
|
238
|
+
grant(grant: ToolConsentGrant): Promise<void>;
|
|
239
|
+
hasConsent(grant: ToolConsentGrant): Promise<boolean>;
|
|
240
|
+
list(tenantId?: string): Promise<ToolConsentGrant[]>;
|
|
241
|
+
}
|
|
242
|
+
declare class InMemoryToolConsentStore implements ToolConsentStore {
|
|
243
|
+
#private;
|
|
244
|
+
grant(grant: ToolConsentGrant): Promise<void>;
|
|
245
|
+
hasConsent(grant: ToolConsentGrant): Promise<boolean>;
|
|
246
|
+
list(tenantId?: string): Promise<ToolConsentGrant[]>;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
interface ToolDebugEntry {
|
|
250
|
+
readonly at: string;
|
|
251
|
+
readonly type: "tool_call" | "connect" | "inspect";
|
|
252
|
+
readonly requestId?: string;
|
|
253
|
+
readonly tenantId?: string;
|
|
254
|
+
readonly serverId?: string;
|
|
255
|
+
readonly toolName?: string;
|
|
256
|
+
readonly ok: boolean;
|
|
257
|
+
readonly durationMs?: number;
|
|
258
|
+
readonly error?: string;
|
|
259
|
+
readonly suggestion?: string;
|
|
260
|
+
}
|
|
261
|
+
declare function toolDebugPath(): string;
|
|
262
|
+
declare function appendToolDebug(entry: Omit<ToolDebugEntry, "at"> & {
|
|
263
|
+
at?: string;
|
|
264
|
+
}): Promise<void>;
|
|
265
|
+
declare function readToolDebug(limit?: number): Promise<ToolDebugEntry[]>;
|
|
266
|
+
|
|
267
|
+
interface McpHostOptions {
|
|
268
|
+
readonly registry?: MCPServerRegistry;
|
|
269
|
+
readonly consent?: ToolConsentStore;
|
|
270
|
+
readonly traceStore?: TraceStore;
|
|
271
|
+
readonly eventLog?: EventLog;
|
|
272
|
+
}
|
|
273
|
+
interface LocalMcpServerConfig {
|
|
274
|
+
readonly id: string;
|
|
275
|
+
readonly name: string;
|
|
276
|
+
readonly description: string;
|
|
277
|
+
readonly manifest?: MCPServerManifest;
|
|
278
|
+
readonly tools: readonly ToolDefinition[];
|
|
279
|
+
readonly handlers: Record<string, MCPToolHandler>;
|
|
280
|
+
readonly allowedPlans?: readonly string[];
|
|
281
|
+
readonly allowedTenants?: readonly string[];
|
|
282
|
+
}
|
|
283
|
+
interface RemoteMcpConnectOptions {
|
|
284
|
+
readonly id: string;
|
|
285
|
+
readonly name?: string;
|
|
286
|
+
readonly description?: string;
|
|
287
|
+
readonly manifest: MCPServerManifest;
|
|
288
|
+
readonly headers?: Record<string, string>;
|
|
289
|
+
}
|
|
290
|
+
declare class McpHost {
|
|
291
|
+
#private;
|
|
292
|
+
constructor(options?: McpHostOptions);
|
|
293
|
+
get registry(): MCPServerRegistry;
|
|
294
|
+
connectLocal(config: LocalMcpServerConfig): void;
|
|
295
|
+
connectStdio(command: string, args: readonly string[], options: RemoteMcpConnectOptions): Promise<void>;
|
|
296
|
+
connectStreamableHttp(endpoint: string, options: RemoteMcpConnectOptions): Promise<void>;
|
|
297
|
+
callTool(toolName: string, args: Record<string, unknown>, context: MCPContext): Promise<ToolExecutionResult>;
|
|
298
|
+
listTools(context: MCPContext): Array<ToolDefinition & {
|
|
299
|
+
serverId: string;
|
|
300
|
+
}>;
|
|
301
|
+
inspect(serverId: string): MCPServerConfig;
|
|
302
|
+
doctor(): Promise<{
|
|
303
|
+
ok: boolean;
|
|
304
|
+
servers: Array<{
|
|
305
|
+
id: string;
|
|
306
|
+
name: string;
|
|
307
|
+
transport: MCPServerConfig["transport"];
|
|
308
|
+
tools: number;
|
|
309
|
+
manifest?: MCPServerManifest;
|
|
310
|
+
}>;
|
|
311
|
+
suggestion?: string;
|
|
312
|
+
}>;
|
|
313
|
+
debug(limit?: number): Promise<ToolDebugEntry[]>;
|
|
314
|
+
close(): Promise<void>;
|
|
315
|
+
}
|
|
316
|
+
declare const toolConsentStore: InMemoryToolConsentStore;
|
|
317
|
+
declare const mcpHost: McpHost;
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* MCP Middleware for rate limiting, audit logging, and access control
|
|
321
|
+
*/
|
|
322
|
+
interface MCPMiddlewareContext extends MCPContext {
|
|
323
|
+
toolName: string;
|
|
324
|
+
arguments: Record<string, unknown>;
|
|
325
|
+
}
|
|
326
|
+
type MCPMiddlewareNext = () => Promise<ToolExecutionResult>;
|
|
327
|
+
type MCPMiddleware = (ctx: MCPMiddlewareContext, next: MCPMiddlewareNext) => Promise<ToolExecutionResult>;
|
|
328
|
+
/**
|
|
329
|
+
* Rate limiting middleware for MCP calls
|
|
330
|
+
*/
|
|
331
|
+
declare function createRateLimitMiddleware(options: {
|
|
332
|
+
maxRequests: number;
|
|
333
|
+
windowMs: number;
|
|
334
|
+
}): MCPMiddleware;
|
|
335
|
+
/**
|
|
336
|
+
* Audit logging middleware
|
|
337
|
+
*/
|
|
338
|
+
declare function createAuditMiddleware(options: {
|
|
339
|
+
onLog: (entry: AuditLogEntry) => void | Promise<void>;
|
|
340
|
+
}): MCPMiddleware;
|
|
341
|
+
interface AuditLogEntry {
|
|
342
|
+
timestamp: string;
|
|
343
|
+
requestId: string;
|
|
344
|
+
tenantId?: string;
|
|
345
|
+
userId?: string;
|
|
346
|
+
toolName: string;
|
|
347
|
+
arguments: Record<string, unknown>;
|
|
348
|
+
success: boolean;
|
|
349
|
+
duration: number;
|
|
350
|
+
error?: string;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Tool access control middleware
|
|
354
|
+
*/
|
|
355
|
+
declare function createAccessControlMiddleware(options: {
|
|
356
|
+
blockedTools?: string[];
|
|
357
|
+
allowedTools?: string[];
|
|
358
|
+
}): MCPMiddleware;
|
|
359
|
+
/**
|
|
360
|
+
* Compose multiple middlewares
|
|
361
|
+
*/
|
|
362
|
+
declare function composeMCPMiddleware(middlewares: MCPMiddleware[]): MCPMiddleware;
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Register internal Nebutra services as MCP servers
|
|
366
|
+
* These wrap our existing microservices with MCP-compatible interfaces
|
|
367
|
+
*/
|
|
368
|
+
declare const INTERNAL_SERVERS: MCPServerConfig[];
|
|
369
|
+
/**
|
|
370
|
+
* Register all internal servers
|
|
371
|
+
*/
|
|
372
|
+
declare function registerInternalServers(): void;
|
|
373
|
+
/**
|
|
374
|
+
* Get list of internal server IDs
|
|
375
|
+
*/
|
|
376
|
+
declare function getInternalServerIds(): string[];
|
|
377
|
+
|
|
378
|
+
export { type AuditLogEntry, INTERNAL_SERVERS, InMemoryToolConsentStore, MCPClient, type MCPContext, type MCPError, type MCPMiddleware, type MCPMiddlewareContext, type MCPRequest, type MCPResponse, type MCPServerConfig, type MCPServerManifest, MCPServerRegistry, type MCPToolHandler, McpHost, type SmitheryConfig, type SmitheryServerInfo, type ToolConsentGrant, type ToolConsentStore, type ToolDebugEntry, type ToolDefinition, ToolDefinitionSchema, type ToolExecutionRequest, type ToolExecutionResult, type ToolParameter, ToolParameterSchema, appendToolDebug, composeMCPMiddleware, createAccessControlMiddleware, createAuditMiddleware, createRateLimitMiddleware, getInternalServerIds, mcpClient, mcpHost, readToolDebug, registerInternalServers, serverRegistry, toolConsentStore, toolDebugPath };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
INTERNAL_SERVERS,
|
|
3
|
+
InMemoryToolConsentStore,
|
|
4
|
+
MCPClient,
|
|
5
|
+
MCPServerRegistry,
|
|
6
|
+
McpHost,
|
|
7
|
+
ToolDefinitionSchema,
|
|
8
|
+
ToolParameterSchema,
|
|
9
|
+
appendToolDebug,
|
|
10
|
+
composeMCPMiddleware,
|
|
11
|
+
createAccessControlMiddleware,
|
|
12
|
+
createAuditMiddleware,
|
|
13
|
+
createRateLimitMiddleware,
|
|
14
|
+
getInternalServerIds,
|
|
15
|
+
mcpClient,
|
|
16
|
+
mcpHost,
|
|
17
|
+
readToolDebug,
|
|
18
|
+
registerInternalServers,
|
|
19
|
+
serverRegistry,
|
|
20
|
+
toolConsentStore,
|
|
21
|
+
toolDebugPath
|
|
22
|
+
} from "./chunk-ORGYGQJV.js";
|
|
23
|
+
export {
|
|
24
|
+
INTERNAL_SERVERS,
|
|
25
|
+
InMemoryToolConsentStore,
|
|
26
|
+
MCPClient,
|
|
27
|
+
MCPServerRegistry,
|
|
28
|
+
McpHost,
|
|
29
|
+
ToolDefinitionSchema,
|
|
30
|
+
ToolParameterSchema,
|
|
31
|
+
appendToolDebug,
|
|
32
|
+
composeMCPMiddleware,
|
|
33
|
+
createAccessControlMiddleware,
|
|
34
|
+
createAuditMiddleware,
|
|
35
|
+
createRateLimitMiddleware,
|
|
36
|
+
getInternalServerIds,
|
|
37
|
+
mcpClient,
|
|
38
|
+
mcpHost,
|
|
39
|
+
readToolDebug,
|
|
40
|
+
registerInternalServers,
|
|
41
|
+
serverRegistry,
|
|
42
|
+
toolConsentStore,
|
|
43
|
+
toolDebugPath
|
|
44
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
declare function createContextServerHandlers(projectRoot: string): {
|
|
3
|
+
listResources(): Promise<{
|
|
4
|
+
resources: {
|
|
5
|
+
uri: string;
|
|
6
|
+
name: "Nebutra Configuration" | "Database Schema Overview";
|
|
7
|
+
mimeType: "application/json" | "text/plain";
|
|
8
|
+
description: "Global configurations for the Nebutra template including enabled features (auth, payments, i18n, db)." | "The core Prisma schema defining the database tables and relationships.";
|
|
9
|
+
}[];
|
|
10
|
+
}>;
|
|
11
|
+
readResource({ uri }: {
|
|
12
|
+
uri: string;
|
|
13
|
+
}): Promise<{
|
|
14
|
+
contents: {
|
|
15
|
+
uri: string;
|
|
16
|
+
mimeType: "application/json" | "text/plain";
|
|
17
|
+
text: string;
|
|
18
|
+
}[];
|
|
19
|
+
}>;
|
|
20
|
+
listTools(): Promise<{
|
|
21
|
+
tools: {
|
|
22
|
+
name: string;
|
|
23
|
+
description: string;
|
|
24
|
+
inputSchema: {
|
|
25
|
+
type: string;
|
|
26
|
+
properties: {};
|
|
27
|
+
required: never[];
|
|
28
|
+
};
|
|
29
|
+
}[];
|
|
30
|
+
}>;
|
|
31
|
+
callTool({ name }: {
|
|
32
|
+
name: string;
|
|
33
|
+
arguments?: Record<string, unknown> | undefined;
|
|
34
|
+
}): Promise<{
|
|
35
|
+
content: {
|
|
36
|
+
type: string;
|
|
37
|
+
text: string;
|
|
38
|
+
}[];
|
|
39
|
+
isError?: never;
|
|
40
|
+
} | {
|
|
41
|
+
content: {
|
|
42
|
+
type: string;
|
|
43
|
+
text: string;
|
|
44
|
+
}[];
|
|
45
|
+
isError: boolean;
|
|
46
|
+
}>;
|
|
47
|
+
};
|
|
48
|
+
declare const startContextServer: () => void;
|
|
49
|
+
|
|
50
|
+
export { createContextServerHandlers, startContextServer };
|