@roarkanalytics/sdk-mcp 2.19.1 → 2.22.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/README.md +1 -1
- package/code-tool.d.mts +4 -1
- package/code-tool.d.mts.map +1 -1
- package/code-tool.d.ts +4 -1
- package/code-tool.d.ts.map +1 -1
- package/code-tool.js +14 -1
- package/code-tool.js.map +1 -1
- package/code-tool.mjs +14 -1
- package/code-tool.mjs.map +1 -1
- package/http.d.mts.map +1 -1
- package/http.d.ts.map +1 -1
- package/http.js +2 -1
- package/http.js.map +1 -1
- package/http.mjs +2 -1
- package/http.mjs.map +1 -1
- package/index.js +1 -1
- package/index.js.map +1 -1
- package/index.mjs +1 -1
- package/index.mjs.map +1 -1
- package/methods.d.mts +10 -0
- package/methods.d.mts.map +1 -0
- package/methods.d.ts +10 -0
- package/methods.d.ts.map +1 -0
- package/methods.js +214 -0
- package/methods.js.map +1 -0
- package/methods.mjs +210 -0
- package/methods.mjs.map +1 -0
- package/options.d.mts +3 -0
- package/options.d.mts.map +1 -1
- package/options.d.ts +3 -0
- package/options.d.ts.map +1 -1
- package/options.js +17 -0
- package/options.js.map +1 -1
- package/options.mjs +17 -0
- package/options.mjs.map +1 -1
- package/package.json +124 -17
- package/server.d.mts.map +1 -1
- package/server.d.ts.map +1 -1
- package/server.js +43 -3
- package/server.js.map +1 -1
- package/server.mjs +44 -4
- package/server.mjs.map +1 -1
- package/src/code-tool.ts +20 -1
- package/src/http.ts +3 -0
- package/src/index.ts +1 -1
- package/src/methods.ts +234 -0
- package/src/options.ts +23 -0
- package/src/server.ts +52 -4
- package/src/stdio.ts +3 -2
- package/stdio.d.mts +2 -1
- package/stdio.d.mts.map +1 -1
- package/stdio.d.ts +2 -1
- package/stdio.d.ts.map +1 -1
- package/stdio.js +2 -2
- package/stdio.js.map +1 -1
- package/stdio.mjs +2 -2
- package/stdio.mjs.map +1 -1
package/server.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
2
2
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
-
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, SetLevelRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
4
4
|
import Roark from '@roarkanalytics/sdk';
|
|
5
5
|
import { codeTool } from "./code-tool.mjs";
|
|
6
6
|
import docsSearchTool from "./docs-search-tool.mjs";
|
|
7
|
+
import { blockedMethodsForCodeTool } from "./methods.mjs";
|
|
7
8
|
async function getInstructions() {
|
|
8
9
|
// This API key is optional; providing it allows the server to fetch instructions for unreleased versions.
|
|
9
10
|
const stainlessAPIKey = readEnv('STAINLESS_API_KEY');
|
|
@@ -32,7 +33,7 @@ async function getInstructions() {
|
|
|
32
33
|
}
|
|
33
34
|
export const newMcpServer = async () => new McpServer({
|
|
34
35
|
name: 'roarkanalytics_sdk_api',
|
|
35
|
-
version: '2.
|
|
36
|
+
version: '2.22.0',
|
|
36
37
|
}, {
|
|
37
38
|
instructions: await getInstructions(),
|
|
38
39
|
capabilities: { tools: {}, logging: {} },
|
|
@@ -43,7 +44,20 @@ export const newMcpServer = async () => new McpServer({
|
|
|
43
44
|
*/
|
|
44
45
|
export async function initMcpServer(params) {
|
|
45
46
|
const server = params.server instanceof McpServer ? params.server.server : params.server;
|
|
46
|
-
const
|
|
47
|
+
const logAtLevel = (level) => (message, ...rest) => {
|
|
48
|
+
void server.sendLoggingMessage({
|
|
49
|
+
level,
|
|
50
|
+
data: { message, rest },
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
const logger = {
|
|
54
|
+
debug: logAtLevel('debug'),
|
|
55
|
+
info: logAtLevel('info'),
|
|
56
|
+
warn: logAtLevel('warning'),
|
|
57
|
+
error: logAtLevel('error'),
|
|
58
|
+
};
|
|
59
|
+
let client = new Roark({
|
|
60
|
+
logger,
|
|
47
61
|
...params.clientOptions,
|
|
48
62
|
defaultHeaders: {
|
|
49
63
|
...params.clientOptions?.defaultHeaders,
|
|
@@ -65,12 +79,38 @@ export async function initMcpServer(params) {
|
|
|
65
79
|
}
|
|
66
80
|
return executeHandler(mcpTool.handler, client, args);
|
|
67
81
|
});
|
|
82
|
+
server.setRequestHandler(SetLevelRequestSchema, async (request) => {
|
|
83
|
+
const { level } = request.params;
|
|
84
|
+
switch (level) {
|
|
85
|
+
case 'debug':
|
|
86
|
+
client = client.withOptions({ logLevel: 'debug' });
|
|
87
|
+
break;
|
|
88
|
+
case 'info':
|
|
89
|
+
client = client.withOptions({ logLevel: 'info' });
|
|
90
|
+
break;
|
|
91
|
+
case 'notice':
|
|
92
|
+
case 'warning':
|
|
93
|
+
client = client.withOptions({ logLevel: 'warn' });
|
|
94
|
+
break;
|
|
95
|
+
case 'error':
|
|
96
|
+
client = client.withOptions({ logLevel: 'error' });
|
|
97
|
+
break;
|
|
98
|
+
default:
|
|
99
|
+
client = client.withOptions({ logLevel: 'off' });
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
return {};
|
|
103
|
+
});
|
|
68
104
|
}
|
|
69
105
|
/**
|
|
70
106
|
* Selects the tools to include in the MCP Server based on the provided options.
|
|
71
107
|
*/
|
|
72
108
|
export function selectTools(options) {
|
|
73
|
-
const includedTools = [
|
|
109
|
+
const includedTools = [
|
|
110
|
+
codeTool({
|
|
111
|
+
blockedMethods: blockedMethodsForCodeTool(options),
|
|
112
|
+
}),
|
|
113
|
+
];
|
|
74
114
|
if (options?.includeDocsTools ?? true) {
|
|
75
115
|
includedTools.push(docsSearchTool);
|
|
76
116
|
}
|
package/server.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.mjs","sourceRoot":"","sources":["src/server.ts"],"names":[],"mappings":"AAAA,sFAAsF;OAG/E,EAAE,SAAS,EAAE,MAAM,yCAAyC;OAC5D,
|
|
1
|
+
{"version":3,"file":"server.mjs","sourceRoot":"","sources":["src/server.ts"],"names":[],"mappings":"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"}
|
package/src/code-tool.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { McpTool, Metadata, ToolCallResult, asErrorResult, asTextContentResult }
|
|
|
4
4
|
import { Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
5
5
|
import { readEnv, requireValue } from './server';
|
|
6
6
|
import { WorkerInput, WorkerOutput } from './code-tool-types';
|
|
7
|
+
import { SdkMethod } from './methods';
|
|
7
8
|
import { Roark } from '@roarkanalytics/sdk';
|
|
8
9
|
|
|
9
10
|
const prompt = `Runs JavaScript code to interact with the Roark API.
|
|
@@ -35,7 +36,7 @@ Variables will not persist between calls, so make sure to return or log any data
|
|
|
35
36
|
*
|
|
36
37
|
* @param endpoints - The endpoints to include in the list.
|
|
37
38
|
*/
|
|
38
|
-
export function codeTool(): McpTool {
|
|
39
|
+
export function codeTool(params: { blockedMethods: SdkMethod[] | undefined }): McpTool {
|
|
39
40
|
const metadata: Metadata = { resource: 'all', operation: 'write', tags: [] };
|
|
40
41
|
const tool: Tool = {
|
|
41
42
|
name: 'execute',
|
|
@@ -59,6 +60,24 @@ export function codeTool(): McpTool {
|
|
|
59
60
|
const code = args.code as string;
|
|
60
61
|
const intent = args.intent as string | undefined;
|
|
61
62
|
|
|
63
|
+
// Do very basic blocking of code that includes forbidden method names.
|
|
64
|
+
//
|
|
65
|
+
// WARNING: This is not secure against obfuscation and other evasion methods. If
|
|
66
|
+
// stronger security blocks are required, then these should be enforced in the downstream
|
|
67
|
+
// API (e.g., by having users call the MCP server with API keys with limited permissions).
|
|
68
|
+
if (params.blockedMethods) {
|
|
69
|
+
const blockedMatches = params.blockedMethods.filter((method) =>
|
|
70
|
+
code.includes(method.fullyQualifiedName),
|
|
71
|
+
);
|
|
72
|
+
if (blockedMatches.length > 0) {
|
|
73
|
+
return asErrorResult(
|
|
74
|
+
`The following methods have been blocked by the MCP server and cannot be used in code execution: ${blockedMatches
|
|
75
|
+
.map((m) => m.fullyQualifiedName)
|
|
76
|
+
.join(', ')}`,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
62
81
|
// this is not required, but passing a Stainless API key for the matching project_name
|
|
63
82
|
// will allow you to run code-mode queries against non-published versions of your SDK.
|
|
64
83
|
const stainlessAPIKey = readEnv('STAINLESS_API_KEY');
|
package/src/http.ts
CHANGED
|
@@ -11,10 +11,12 @@ import { parseAuthHeaders } from './headers';
|
|
|
11
11
|
|
|
12
12
|
const newServer = async ({
|
|
13
13
|
clientOptions,
|
|
14
|
+
mcpOptions,
|
|
14
15
|
req,
|
|
15
16
|
res,
|
|
16
17
|
}: {
|
|
17
18
|
clientOptions: ClientOptions;
|
|
19
|
+
mcpOptions: McpOptions;
|
|
18
20
|
req: express.Request;
|
|
19
21
|
res: express.Response;
|
|
20
22
|
}): Promise<McpServer | null> => {
|
|
@@ -24,6 +26,7 @@ const newServer = async ({
|
|
|
24
26
|
const authOptions = parseAuthHeaders(req, false);
|
|
25
27
|
await initMcpServer({
|
|
26
28
|
server: server,
|
|
29
|
+
mcpOptions: mcpOptions,
|
|
27
30
|
clientOptions: {
|
|
28
31
|
...clientOptions,
|
|
29
32
|
...authOptions,
|
package/src/index.ts
CHANGED
package/src/methods.ts
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { McpOptions } from './options';
|
|
2
|
+
|
|
3
|
+
export type SdkMethod = {
|
|
4
|
+
clientCallName: string;
|
|
5
|
+
fullyQualifiedName: string;
|
|
6
|
+
httpMethod?: 'get' | 'post' | 'put' | 'patch' | 'delete' | 'query';
|
|
7
|
+
httpPath?: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const sdkMethods: SdkMethod[] = [
|
|
11
|
+
{
|
|
12
|
+
clientCallName: 'client.health.get',
|
|
13
|
+
fullyQualifiedName: 'health.get',
|
|
14
|
+
httpMethod: 'get',
|
|
15
|
+
httpPath: '/health',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
clientCallName: 'client.evaluation.createJob',
|
|
19
|
+
fullyQualifiedName: 'evaluation.createJob',
|
|
20
|
+
httpMethod: 'post',
|
|
21
|
+
httpPath: '/v1/evaluation/job',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
clientCallName: 'client.evaluation.getEvaluatorByID',
|
|
25
|
+
fullyQualifiedName: 'evaluation.getEvaluatorByID',
|
|
26
|
+
httpMethod: 'get',
|
|
27
|
+
httpPath: '/v1/evaluation/evaluators/{evaluatorId}',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
clientCallName: 'client.evaluation.getJob',
|
|
31
|
+
fullyQualifiedName: 'evaluation.getJob',
|
|
32
|
+
httpMethod: 'get',
|
|
33
|
+
httpPath: '/v1/evaluation/job/{jobId}',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
clientCallName: 'client.evaluation.listEvaluators',
|
|
37
|
+
fullyQualifiedName: 'evaluation.listEvaluators',
|
|
38
|
+
httpMethod: 'get',
|
|
39
|
+
httpPath: '/v1/evaluation/evaluators',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
clientCallName: 'client.evaluation.listJobRuns',
|
|
43
|
+
fullyQualifiedName: 'evaluation.listJobRuns',
|
|
44
|
+
httpMethod: 'get',
|
|
45
|
+
httpPath: '/v1/evaluation/job/{jobId}/runs',
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
clientCallName: 'client.call.create',
|
|
49
|
+
fullyQualifiedName: 'call.create',
|
|
50
|
+
httpMethod: 'post',
|
|
51
|
+
httpPath: '/v1/call',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
clientCallName: 'client.call.list',
|
|
55
|
+
fullyQualifiedName: 'call.list',
|
|
56
|
+
httpMethod: 'get',
|
|
57
|
+
httpPath: '/v1/call',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
clientCallName: 'client.call.getByID',
|
|
61
|
+
fullyQualifiedName: 'call.getByID',
|
|
62
|
+
httpMethod: 'get',
|
|
63
|
+
httpPath: '/v1/call/{callId}',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
clientCallName: 'client.call.listEvaluationRuns',
|
|
67
|
+
fullyQualifiedName: 'call.listEvaluationRuns',
|
|
68
|
+
httpMethod: 'get',
|
|
69
|
+
httpPath: '/v1/call/{callId}/evaluation-run',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
clientCallName: 'client.call.listMetrics',
|
|
73
|
+
fullyQualifiedName: 'call.listMetrics',
|
|
74
|
+
httpMethod: 'get',
|
|
75
|
+
httpPath: '/v1/call/{callId}/metrics',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
clientCallName: 'client.call.listSentimentRuns',
|
|
79
|
+
fullyQualifiedName: 'call.listSentimentRuns',
|
|
80
|
+
httpMethod: 'get',
|
|
81
|
+
httpPath: '/v1/call/{callId}/sentiment-run',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
clientCallName: 'client.metric.listDefinitions',
|
|
85
|
+
fullyQualifiedName: 'metric.listDefinitions',
|
|
86
|
+
httpMethod: 'get',
|
|
87
|
+
httpPath: '/v1/metric/definitions',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
clientCallName: 'client.integrations.createRetellCall',
|
|
91
|
+
fullyQualifiedName: 'integrations.createRetellCall',
|
|
92
|
+
httpMethod: 'post',
|
|
93
|
+
httpPath: '/v1/retell/call',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
clientCallName: 'client.integrations.createVapiCall',
|
|
97
|
+
fullyQualifiedName: 'integrations.createVapiCall',
|
|
98
|
+
httpMethod: 'post',
|
|
99
|
+
httpPath: '/v1/vapi/call',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
clientCallName: 'client.simulation.getRunPlanJob',
|
|
103
|
+
fullyQualifiedName: 'simulation.getRunPlanJob',
|
|
104
|
+
httpMethod: 'get',
|
|
105
|
+
httpPath: '/v1/simulation/plan/job/{jobId}',
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
clientCallName: 'client.simulation.getSimulationJobByID',
|
|
109
|
+
fullyQualifiedName: 'simulation.getSimulationJobByID',
|
|
110
|
+
httpMethod: 'get',
|
|
111
|
+
httpPath: '/v1/simulation/job/{jobId}',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
clientCallName: 'client.simulation.listRunPlanJobs',
|
|
115
|
+
fullyQualifiedName: 'simulation.listRunPlanJobs',
|
|
116
|
+
httpMethod: 'get',
|
|
117
|
+
httpPath: '/v1/simulation/plan/jobs',
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
clientCallName: 'client.simulation.listScenarios',
|
|
121
|
+
fullyQualifiedName: 'simulation.listScenarios',
|
|
122
|
+
httpMethod: 'get',
|
|
123
|
+
httpPath: '/v1/simulation/scenario',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
clientCallName: 'client.simulation.lookupSimulationJob',
|
|
127
|
+
fullyQualifiedName: 'simulation.lookupSimulationJob',
|
|
128
|
+
httpMethod: 'get',
|
|
129
|
+
httpPath: '/v1/simulation/job/lookup',
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
clientCallName: 'client.simulation.startRunPlanJob',
|
|
133
|
+
fullyQualifiedName: 'simulation.startRunPlanJob',
|
|
134
|
+
httpMethod: 'post',
|
|
135
|
+
httpPath: '/v1/simulation/plan/{planId}/job',
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
clientCallName: 'client.persona.create',
|
|
139
|
+
fullyQualifiedName: 'persona.create',
|
|
140
|
+
httpMethod: 'post',
|
|
141
|
+
httpPath: '/v1/persona',
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
clientCallName: 'client.persona.update',
|
|
145
|
+
fullyQualifiedName: 'persona.update',
|
|
146
|
+
httpMethod: 'put',
|
|
147
|
+
httpPath: '/v1/persona/{personaId}',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
clientCallName: 'client.persona.list',
|
|
151
|
+
fullyQualifiedName: 'persona.list',
|
|
152
|
+
httpMethod: 'get',
|
|
153
|
+
httpPath: '/v1/persona',
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
clientCallName: 'client.persona.getByID',
|
|
157
|
+
fullyQualifiedName: 'persona.getByID',
|
|
158
|
+
httpMethod: 'get',
|
|
159
|
+
httpPath: '/v1/persona/{personaId}',
|
|
160
|
+
},
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
function allowedMethodsForCodeTool(options: McpOptions | undefined): SdkMethod[] | undefined {
|
|
164
|
+
if (!options) {
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
let allowedMethods: SdkMethod[];
|
|
169
|
+
|
|
170
|
+
if (options.codeAllowHttpGets || options.codeAllowedMethods) {
|
|
171
|
+
// Start with nothing allowed and then add into it from options
|
|
172
|
+
let allowedMethodsSet = new Set<SdkMethod>();
|
|
173
|
+
|
|
174
|
+
if (options.codeAllowHttpGets) {
|
|
175
|
+
// Add all methods that map to an HTTP GET
|
|
176
|
+
sdkMethods
|
|
177
|
+
.filter((method) => method.httpMethod === 'get')
|
|
178
|
+
.forEach((method) => allowedMethodsSet.add(method));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (options.codeAllowedMethods) {
|
|
182
|
+
// Add all methods that match any of the allowed regexps
|
|
183
|
+
const allowedRegexps = options.codeAllowedMethods.map((pattern) => {
|
|
184
|
+
try {
|
|
185
|
+
return new RegExp(pattern);
|
|
186
|
+
} catch (e) {
|
|
187
|
+
throw new Error(
|
|
188
|
+
`Invalid regex pattern for allowed method: "${pattern}": ${e instanceof Error ? e.message : e}`,
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
sdkMethods
|
|
194
|
+
.filter((method) => allowedRegexps.some((regexp) => regexp.test(method.fullyQualifiedName)))
|
|
195
|
+
.forEach((method) => allowedMethodsSet.add(method));
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
allowedMethods = Array.from(allowedMethodsSet);
|
|
199
|
+
} else {
|
|
200
|
+
// Start with everything allowed
|
|
201
|
+
allowedMethods = [...sdkMethods];
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (options.codeBlockedMethods) {
|
|
205
|
+
// Filter down based on blocked regexps
|
|
206
|
+
const blockedRegexps = options.codeBlockedMethods.map((pattern) => {
|
|
207
|
+
try {
|
|
208
|
+
return new RegExp(pattern);
|
|
209
|
+
} catch (e) {
|
|
210
|
+
throw new Error(
|
|
211
|
+
`Invalid regex pattern for blocked method: "${pattern}": ${e instanceof Error ? e.message : e}`,
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
allowedMethods = allowedMethods.filter(
|
|
217
|
+
(method) => !blockedRegexps.some((regexp) => regexp.test(method.fullyQualifiedName)),
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return allowedMethods;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export function blockedMethodsForCodeTool(options: McpOptions | undefined): SdkMethod[] | undefined {
|
|
225
|
+
const allowedMethods = allowedMethodsForCodeTool(options);
|
|
226
|
+
if (!allowedMethods) {
|
|
227
|
+
return undefined;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const allowedSet = new Set(allowedMethods.map((method) => method.fullyQualifiedName));
|
|
231
|
+
|
|
232
|
+
// Return any methods that are not explicitly allowed
|
|
233
|
+
return sdkMethods.filter((method) => !allowedSet.has(method.fullyQualifiedName));
|
|
234
|
+
}
|
package/src/options.ts
CHANGED
|
@@ -12,10 +12,30 @@ export type CLIOptions = McpOptions & {
|
|
|
12
12
|
|
|
13
13
|
export type McpOptions = {
|
|
14
14
|
includeDocsTools?: boolean | undefined;
|
|
15
|
+
codeAllowHttpGets?: boolean | undefined;
|
|
16
|
+
codeAllowedMethods?: string[] | undefined;
|
|
17
|
+
codeBlockedMethods?: string[] | undefined;
|
|
15
18
|
};
|
|
16
19
|
|
|
17
20
|
export function parseCLIOptions(): CLIOptions {
|
|
18
21
|
const opts = yargs(hideBin(process.argv))
|
|
22
|
+
.option('code-allow-http-gets', {
|
|
23
|
+
type: 'boolean',
|
|
24
|
+
description:
|
|
25
|
+
'Allow all code tool methods that map to HTTP GET operations. If all code-allow-* flags are unset, then everything is allowed.',
|
|
26
|
+
})
|
|
27
|
+
.option('code-allowed-methods', {
|
|
28
|
+
type: 'string',
|
|
29
|
+
array: true,
|
|
30
|
+
description:
|
|
31
|
+
'Methods to explicitly allow for code tool. Evaluated as regular expressions against method fully qualified names. If all code-allow-* flags are unset, then everything is allowed.',
|
|
32
|
+
})
|
|
33
|
+
.option('code-blocked-methods', {
|
|
34
|
+
type: 'string',
|
|
35
|
+
array: true,
|
|
36
|
+
description:
|
|
37
|
+
'Methods to explicitly block for code tool. Evaluated as regular expressions against method fully qualified names. If all code-allow-* flags are unset, then everything is allowed.',
|
|
38
|
+
})
|
|
19
39
|
.option('debug', { type: 'boolean', description: 'Enable debug logging' })
|
|
20
40
|
.option('no-tools', {
|
|
21
41
|
type: 'string',
|
|
@@ -59,6 +79,9 @@ export function parseCLIOptions(): CLIOptions {
|
|
|
59
79
|
return {
|
|
60
80
|
...(includeDocsTools !== undefined && { includeDocsTools }),
|
|
61
81
|
debug: !!argv.debug,
|
|
82
|
+
codeAllowHttpGets: argv.codeAllowHttpGets,
|
|
83
|
+
codeAllowedMethods: argv.codeAllowedMethods,
|
|
84
|
+
codeBlockedMethods: argv.codeBlockedMethods,
|
|
62
85
|
transport,
|
|
63
86
|
port: argv.port,
|
|
64
87
|
socket: argv.socket,
|
package/src/server.ts
CHANGED
|
@@ -2,12 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
4
4
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
CallToolRequestSchema,
|
|
7
|
+
ListToolsRequestSchema,
|
|
8
|
+
SetLevelRequestSchema,
|
|
9
|
+
} from '@modelcontextprotocol/sdk/types.js';
|
|
6
10
|
import { ClientOptions } from '@roarkanalytics/sdk';
|
|
7
11
|
import Roark from '@roarkanalytics/sdk';
|
|
8
12
|
import { codeTool } from './code-tool';
|
|
9
13
|
import docsSearchTool from './docs-search-tool';
|
|
10
14
|
import { McpOptions } from './options';
|
|
15
|
+
import { blockedMethodsForCodeTool } from './methods';
|
|
11
16
|
import { HandlerFunction, McpTool } from './types';
|
|
12
17
|
|
|
13
18
|
export { McpOptions } from './options';
|
|
@@ -53,7 +58,7 @@ export const newMcpServer = async () =>
|
|
|
53
58
|
new McpServer(
|
|
54
59
|
{
|
|
55
60
|
name: 'roarkanalytics_sdk_api',
|
|
56
|
-
version: '2.
|
|
61
|
+
version: '2.22.0',
|
|
57
62
|
},
|
|
58
63
|
{
|
|
59
64
|
instructions: await getInstructions(),
|
|
@@ -72,7 +77,23 @@ export async function initMcpServer(params: {
|
|
|
72
77
|
}) {
|
|
73
78
|
const server = params.server instanceof McpServer ? params.server.server : params.server;
|
|
74
79
|
|
|
75
|
-
const
|
|
80
|
+
const logAtLevel =
|
|
81
|
+
(level: 'debug' | 'info' | 'warning' | 'error') =>
|
|
82
|
+
(message: string, ...rest: unknown[]) => {
|
|
83
|
+
void server.sendLoggingMessage({
|
|
84
|
+
level,
|
|
85
|
+
data: { message, rest },
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
const logger = {
|
|
89
|
+
debug: logAtLevel('debug'),
|
|
90
|
+
info: logAtLevel('info'),
|
|
91
|
+
warn: logAtLevel('warning'),
|
|
92
|
+
error: logAtLevel('error'),
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
let client = new Roark({
|
|
96
|
+
logger,
|
|
76
97
|
...params.clientOptions,
|
|
77
98
|
defaultHeaders: {
|
|
78
99
|
...params.clientOptions?.defaultHeaders,
|
|
@@ -98,13 +119,40 @@ export async function initMcpServer(params: {
|
|
|
98
119
|
|
|
99
120
|
return executeHandler(mcpTool.handler, client, args);
|
|
100
121
|
});
|
|
122
|
+
|
|
123
|
+
server.setRequestHandler(SetLevelRequestSchema, async (request) => {
|
|
124
|
+
const { level } = request.params;
|
|
125
|
+
switch (level) {
|
|
126
|
+
case 'debug':
|
|
127
|
+
client = client.withOptions({ logLevel: 'debug' });
|
|
128
|
+
break;
|
|
129
|
+
case 'info':
|
|
130
|
+
client = client.withOptions({ logLevel: 'info' });
|
|
131
|
+
break;
|
|
132
|
+
case 'notice':
|
|
133
|
+
case 'warning':
|
|
134
|
+
client = client.withOptions({ logLevel: 'warn' });
|
|
135
|
+
break;
|
|
136
|
+
case 'error':
|
|
137
|
+
client = client.withOptions({ logLevel: 'error' });
|
|
138
|
+
break;
|
|
139
|
+
default:
|
|
140
|
+
client = client.withOptions({ logLevel: 'off' });
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
return {};
|
|
144
|
+
});
|
|
101
145
|
}
|
|
102
146
|
|
|
103
147
|
/**
|
|
104
148
|
* Selects the tools to include in the MCP Server based on the provided options.
|
|
105
149
|
*/
|
|
106
150
|
export function selectTools(options?: McpOptions): McpTool[] {
|
|
107
|
-
const includedTools = [
|
|
151
|
+
const includedTools = [
|
|
152
|
+
codeTool({
|
|
153
|
+
blockedMethods: blockedMethodsForCodeTool(options),
|
|
154
|
+
}),
|
|
155
|
+
];
|
|
108
156
|
if (options?.includeDocsTools ?? true) {
|
|
109
157
|
includedTools.push(docsSearchTool);
|
|
110
158
|
}
|
package/src/stdio.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
2
|
+
import { McpOptions } from './options';
|
|
2
3
|
import { initMcpServer, newMcpServer } from './server';
|
|
3
4
|
|
|
4
|
-
export const launchStdioServer = async () => {
|
|
5
|
+
export const launchStdioServer = async (mcpOptions: McpOptions) => {
|
|
5
6
|
const server = await newMcpServer();
|
|
6
7
|
|
|
7
|
-
await initMcpServer({ server });
|
|
8
|
+
await initMcpServer({ server, mcpOptions });
|
|
8
9
|
|
|
9
10
|
const transport = new StdioServerTransport();
|
|
10
11
|
await server.connect(transport);
|
package/stdio.d.mts
CHANGED
package/stdio.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdio.d.mts","sourceRoot":"","sources":["src/stdio.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"stdio.d.mts","sourceRoot":"","sources":["src/stdio.ts"],"names":[],"mappings":"OACO,EAAE,UAAU,EAAE;AAGrB,eAAO,MAAM,iBAAiB,GAAU,YAAY,UAAU,kBAQ7D,CAAC"}
|
package/stdio.d.ts
CHANGED
package/stdio.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["src/stdio.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["src/stdio.ts"],"names":[],"mappings":"OACO,EAAE,UAAU,EAAE;AAGrB,eAAO,MAAM,iBAAiB,GAAU,YAAY,UAAU,kBAQ7D,CAAC"}
|
package/stdio.js
CHANGED
|
@@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.launchStdioServer = void 0;
|
|
4
4
|
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
5
5
|
const server_1 = require("./server.js");
|
|
6
|
-
const launchStdioServer = async () => {
|
|
6
|
+
const launchStdioServer = async (mcpOptions) => {
|
|
7
7
|
const server = await (0, server_1.newMcpServer)();
|
|
8
|
-
await (0, server_1.initMcpServer)({ server });
|
|
8
|
+
await (0, server_1.initMcpServer)({ server, mcpOptions });
|
|
9
9
|
const transport = new stdio_js_1.StdioServerTransport();
|
|
10
10
|
await server.connect(transport);
|
|
11
11
|
console.error('MCP Server running on stdio');
|
package/stdio.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["src/stdio.ts"],"names":[],"mappings":";;;AAAA,wEAAiF;
|
|
1
|
+
{"version":3,"file":"stdio.js","sourceRoot":"","sources":["src/stdio.ts"],"names":[],"mappings":";;;AAAA,wEAAiF;AAEjF,wCAAuD;AAEhD,MAAM,iBAAiB,GAAG,KAAK,EAAE,UAAsB,EAAE,EAAE;IAChE,MAAM,MAAM,GAAG,MAAM,IAAA,qBAAY,GAAE,CAAC;IAEpC,MAAM,IAAA,sBAAa,EAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;IAE5C,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;AAC/C,CAAC,CAAC;AARW,QAAA,iBAAiB,qBAQ5B"}
|
package/stdio.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
2
2
|
import { initMcpServer, newMcpServer } from "./server.mjs";
|
|
3
|
-
export const launchStdioServer = async () => {
|
|
3
|
+
export const launchStdioServer = async (mcpOptions) => {
|
|
4
4
|
const server = await newMcpServer();
|
|
5
|
-
await initMcpServer({ server });
|
|
5
|
+
await initMcpServer({ server, mcpOptions });
|
|
6
6
|
const transport = new StdioServerTransport();
|
|
7
7
|
await server.connect(transport);
|
|
8
8
|
console.error('MCP Server running on stdio');
|
package/stdio.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdio.mjs","sourceRoot":"","sources":["src/stdio.ts"],"names":[],"mappings":"OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C;
|
|
1
|
+
{"version":3,"file":"stdio.mjs","sourceRoot":"","sources":["src/stdio.ts"],"names":[],"mappings":"OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C;OAEzE,EAAE,aAAa,EAAE,YAAY,EAAE;AAEtC,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,UAAsB,EAAE,EAAE;IAChE,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;IAEpC,MAAM,aAAa,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;IAE5C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;AAC/C,CAAC,CAAC"}
|