@roarkanalytics/sdk-mcp 4.42.0 → 4.43.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.
Files changed (68) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +44 -20
  3. package/client-headers.d.mts +2 -2
  4. package/client-headers.d.ts +2 -2
  5. package/client-headers.js +1 -1
  6. package/client-headers.mjs +1 -1
  7. package/code-tool-types.d.mts +0 -1
  8. package/code-tool-types.d.mts.map +1 -1
  9. package/code-tool-types.d.ts +0 -1
  10. package/code-tool-types.d.ts.map +1 -1
  11. package/code-tool.d.mts.map +1 -1
  12. package/code-tool.d.ts.map +1 -1
  13. package/code-tool.js +12 -34
  14. package/code-tool.js.map +1 -1
  15. package/code-tool.mjs +12 -34
  16. package/code-tool.mjs.map +1 -1
  17. package/directory-tools.d.mts +16 -0
  18. package/directory-tools.d.mts.map +1 -0
  19. package/directory-tools.d.ts +16 -0
  20. package/directory-tools.d.ts.map +1 -0
  21. package/directory-tools.js +704 -0
  22. package/directory-tools.js.map +1 -0
  23. package/directory-tools.mjs +700 -0
  24. package/directory-tools.mjs.map +1 -0
  25. package/docs-search-tool.d.mts.map +1 -1
  26. package/docs-search-tool.d.ts.map +1 -1
  27. package/docs-search-tool.js +4 -1
  28. package/docs-search-tool.js.map +1 -1
  29. package/docs-search-tool.mjs +4 -1
  30. package/docs-search-tool.mjs.map +1 -1
  31. package/http.d.mts.map +1 -1
  32. package/http.d.ts.map +1 -1
  33. package/http.js +9 -4
  34. package/http.js.map +1 -1
  35. package/http.mjs +9 -4
  36. package/http.mjs.map +1 -1
  37. package/options.d.mts +17 -0
  38. package/options.d.mts.map +1 -1
  39. package/options.d.ts +17 -0
  40. package/options.d.ts.map +1 -1
  41. package/options.js +22 -0
  42. package/options.js.map +1 -1
  43. package/options.mjs +21 -0
  44. package/options.mjs.map +1 -1
  45. package/package.json +11 -1
  46. package/server.d.mts +2 -1
  47. package/server.d.mts.map +1 -1
  48. package/server.d.ts +2 -1
  49. package/server.d.ts.map +1 -1
  50. package/server.js +18 -4
  51. package/server.js.map +1 -1
  52. package/server.mjs +18 -4
  53. package/server.mjs.map +1 -1
  54. package/src/client-headers.ts +1 -1
  55. package/src/code-tool-types.ts +0 -1
  56. package/src/code-tool.ts +14 -34
  57. package/src/directory-tools.ts +987 -0
  58. package/src/docs-search-tool.ts +4 -1
  59. package/src/http.ts +9 -5
  60. package/src/options.ts +33 -0
  61. package/src/server.ts +19 -4
  62. package/src/stdio.ts +2 -1
  63. package/stdio.d.mts.map +1 -1
  64. package/stdio.d.ts.map +1 -1
  65. package/stdio.js +2 -0
  66. package/stdio.js.map +1 -1
  67. package/stdio.mjs +2 -0
  68. package/stdio.mjs.map +1 -1
@@ -14,8 +14,9 @@ export const metadata: Metadata = {
14
14
 
15
15
  export const tool: Tool = {
16
16
  name: 'search_docs',
17
+ title: 'Search Roark docs',
17
18
  description:
18
- 'Search SDK documentation to find methods, parameters, and usage examples for interacting with the API. Use this before writing code when you need to discover the right approach.',
19
+ 'Searches Roark SDK documentation for methods, parameters, and response shapes. Returns the matching documentation for the query and language.',
19
20
  inputSchema: {
20
21
  type: 'object',
21
22
  properties: {
@@ -37,7 +38,9 @@ export const tool: Tool = {
37
38
  required: ['query', 'language'],
38
39
  },
39
40
  annotations: {
41
+ title: 'Search Roark docs',
40
42
  readOnlyHint: true,
43
+ destructiveHint: false,
41
44
  },
42
45
  };
43
46
 
package/src/http.ts CHANGED
@@ -9,7 +9,7 @@ import pino from 'pino';
9
9
  import pinoHttp from 'pino-http';
10
10
  import { getStainlessApiKey, parseClientAuthHeaders } from './auth';
11
11
  import { getLogger } from './logger';
12
- import { McpOptions } from './options';
12
+ import { McpOptions, toolSurfaceFor } from './options';
13
13
  import {
14
14
  Connector,
15
15
  ORIGIN_CONNECTOR,
@@ -49,9 +49,9 @@ const newServer = async ({
49
49
  // token is a Roark API key and is forwarded to the SDK unchanged. Without oauth
50
50
  // config we keep the legacy optional-bearer behavior (local installs).
51
51
  //
52
- // This runs before the server is built on purpose: `newMcpServer` fetches the
53
- // instructions document over the network, and an unauthenticated caller should
54
- // not be able to make us do that.
52
+ // This runs before the server is built on purpose: in code mode `newMcpServer`
53
+ // fetches the instructions document over the network, and an unauthenticated
54
+ // caller should not be able to make us do that. Directory mode does not fetch.
55
55
  let authOptions: Partial<ClientOptions>;
56
56
  if (mcpOptions.oauth) {
57
57
  const connector = connectorFrom(req);
@@ -74,7 +74,11 @@ const newServer = async ({
74
74
 
75
75
  const stainlessApiKey = getStainlessApiKey(req, mcpOptions);
76
76
  const customInstructionsPath = mcpOptions.customInstructionsPath;
77
- const server = await newMcpServer({ stainlessApiKey, customInstructionsPath });
77
+ const server = await newMcpServer({
78
+ stainlessApiKey,
79
+ customInstructionsPath,
80
+ toolSurface: toolSurfaceFor(mcpOptions),
81
+ });
78
82
 
79
83
  let upstreamClientEnvs: Record<string, string> | undefined;
80
84
  const clientEnvsHeader = req.headers['x-stainless-mcp-client-envs'];
package/src/options.ts CHANGED
@@ -25,6 +25,11 @@ export type McpOptions = {
25
25
  codeAllowedMethods?: string[] | undefined;
26
26
  codeBlockedMethods?: string[] | undefined;
27
27
  codeExecutionMode: McpCodeExecutionMode;
28
+ /**
29
+ * Which tool set to expose. Unset means `directory` when `oauth` is set and
30
+ * `code` otherwise. See `toolSurfaceFor`.
31
+ */
32
+ toolSurface?: ToolSurface | undefined;
28
33
  customInstructionsPath?: string | undefined;
29
34
  /**
30
35
  * Remote OAuth resource-server config. When set (http transport), every request
@@ -37,6 +42,23 @@ export type McpOptions = {
37
42
 
38
43
  export type McpCodeExecutionMode = 'stainless-sandbox' | 'local';
39
44
 
45
+ /**
46
+ * `directory` is the Claude connector surface: one named tool per action, reads
47
+ * and writes split. `code` is the local install: `execute` plus docs search.
48
+ */
49
+ export type ToolSurface = 'code' | 'directory';
50
+
51
+ /**
52
+ * OAuth is what the hosted directory server runs with, so that process defaults
53
+ * to the named tools. A local stdio install, and an HTTP server without OAuth,
54
+ * keep the code tool. An explicit `toolSurface` wins over that default, which
55
+ * is how a private server can still opt into code execution.
56
+ */
57
+ export function toolSurfaceFor(options?: Pick<McpOptions, 'toolSurface' | 'oauth'>): ToolSurface {
58
+ if (options?.toolSurface) return options.toolSurface;
59
+ return options?.oauth ? 'directory' : 'code';
60
+ }
61
+
40
62
  export function parseCLIOptions(): CLIOptions {
41
63
  const opts = yargs(hideBin(process.argv))
42
64
  .option('code-allow-http-gets', {
@@ -110,6 +132,12 @@ export function parseCLIOptions(): CLIOptions {
110
132
  description:
111
133
  'API key for Stainless. Used to authenticate requests to Stainless-hosted tools endpoints.',
112
134
  })
135
+ .option('tool-surface', {
136
+ type: 'string',
137
+ choices: ['code', 'directory'],
138
+ description:
139
+ "Which tools to expose. 'directory' is a set of separate read and write tools and is the default when OAuth is enabled. 'code' exposes the code execution tool and is the default otherwise.",
140
+ })
113
141
  .option('tools', {
114
142
  type: 'string',
115
143
  array: true,
@@ -177,6 +205,10 @@ export function parseCLIOptions(): CLIOptions {
177
205
  codeAllowedMethods: argv.codeAllowedMethods,
178
206
  codeBlockedMethods: argv.codeBlockedMethods,
179
207
  codeExecutionMode,
208
+ toolSurface: toolSurfaceFor({
209
+ toolSurface: argv.toolSurface as ToolSurface | undefined,
210
+ ...(oauth && { oauth }),
211
+ }),
180
212
  customInstructionsPath: argv.customInstructionsPath,
181
213
  ...(oauth && { oauth }),
182
214
  transport,
@@ -235,6 +267,7 @@ export function parseQueryOptions(defaultOptions: McpOptions, query: unknown): M
235
267
  ...(codeTool !== undefined && { includeCodeTool: codeTool }),
236
268
  ...(docsTools !== undefined && { includeDocsTools: docsTools }),
237
269
  codeExecutionMode: defaultOptions.codeExecutionMode,
270
+ toolSurface: defaultOptions.toolSurface,
238
271
  docsSearchMode: defaultOptions.docsSearchMode,
239
272
  docsDir: defaultOptions.docsDir,
240
273
  };
package/src/server.ts CHANGED
@@ -10,11 +10,12 @@ import {
10
10
  import { ClientOptions } from '@roarkanalytics/sdk';
11
11
  import Roark from '@roarkanalytics/sdk';
12
12
  import { codeTool } from './code-tool';
13
+ import { DIRECTORY_SERVER_INSTRUCTIONS, directoryTools } from './directory-tools';
13
14
  import docsSearchTool from './docs-search-tool';
14
15
  import { setLocalSearch } from './docs-search-tool';
15
16
  import { LocalDocsSearch } from './local-docs-search';
16
17
  import { getInstructions } from './instructions';
17
- import { McpOptions } from './options';
18
+ import { McpOptions, toolSurfaceFor } from './options';
18
19
  import { blockedMethodsForCodeTool } from './methods';
19
20
  import { HandlerFunction, McpRequestContext, ToolCallResult, McpTool } from './types';
20
21
  import { MCP_CLIENT_HEADERS } from './client-headers';
@@ -22,18 +23,26 @@ import { MCP_CLIENT_HEADERS } from './client-headers';
22
23
  export const newMcpServer = async ({
23
24
  stainlessApiKey,
24
25
  customInstructionsPath,
26
+ toolSurface,
25
27
  }: {
26
28
  stainlessApiKey?: string | undefined;
27
29
  customInstructionsPath?: string | undefined;
30
+ toolSurface?: McpOptions['toolSurface'] | undefined;
28
31
  }) =>
29
32
  new McpServer(
30
33
  {
31
34
  name: 'roarkanalytics_sdk_api',
32
35
  // A literal, not MCP_SERVER_VERSION: publish.yml checks dist/server.js for it.
33
- version: '4.42.0', // x-release-please-version
36
+ version: '4.43.0', // x-release-please-version
34
37
  },
35
38
  {
36
- instructions: await getInstructions({ stainlessApiKey, customInstructionsPath }),
39
+ // Directory mode does not fetch instructions. The hosted document tells a
40
+ // model how to write SDK snippets for `execute`, which this surface does
41
+ // not expose, and the directory reviews that kind of instruction.
42
+ instructions:
43
+ toolSurface === 'directory' ?
44
+ DIRECTORY_SERVER_INSTRUCTIONS
45
+ : await getInstructions({ stainlessApiKey, customInstructionsPath }),
37
46
  capabilities: { tools: {}, logging: {} },
38
47
  },
39
48
  );
@@ -213,8 +222,14 @@ export async function initMcpServer(params: {
213
222
  */
214
223
  export function selectTools(options?: McpOptions): McpTool[] {
215
224
  const includedTools = [];
225
+ const surface = toolSurfaceFor(options);
216
226
 
217
- if (options?.includeCodeTool ?? true) {
227
+ if (surface === 'directory') {
228
+ // `includeCodeTool` cannot put `execute` back on this surface. The directory
229
+ // endpoint is the one Claude reviews, and a query or header that re-enabled
230
+ // arbitrary SDK code would put a mixed read/write tool back in front of it.
231
+ includedTools.push(...directoryTools());
232
+ } else if (options?.includeCodeTool ?? true) {
218
233
  includedTools.push(
219
234
  codeTool({
220
235
  blockedMethods: blockedMethodsForCodeTool(options),
package/src/stdio.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
2
- import { McpOptions } from './options';
2
+ import { McpOptions, toolSurfaceFor } from './options';
3
3
  import { initMcpServer, newMcpServer } from './server';
4
4
  import { getLogger } from './logger';
5
5
 
@@ -7,6 +7,7 @@ export const launchStdioServer = async (mcpOptions: McpOptions) => {
7
7
  const server = await newMcpServer({
8
8
  stainlessApiKey: mcpOptions.stainlessApiKey,
9
9
  customInstructionsPath: mcpOptions.customInstructionsPath,
10
+ toolSurface: toolSurfaceFor(mcpOptions),
10
11
  });
11
12
 
12
13
  await initMcpServer({ server, mcpOptions, stainlessApiKey: mcpOptions.stainlessApiKey });
package/stdio.d.mts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"stdio.d.mts","sourceRoot":"","sources":["src/stdio.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,sBAAkB;AAIvC,eAAO,MAAM,iBAAiB,GAAU,YAAY,UAAU,kBAW7D,CAAC"}
1
+ {"version":3,"file":"stdio.d.mts","sourceRoot":"","sources":["src/stdio.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAkB,sBAAkB;AAIvD,eAAO,MAAM,iBAAiB,GAAU,YAAY,UAAU,kBAY7D,CAAC"}
package/stdio.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["src/stdio.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,qBAAkB;AAIvC,eAAO,MAAM,iBAAiB,GAAU,YAAY,UAAU,kBAW7D,CAAC"}
1
+ {"version":3,"file":"stdio.d.ts","sourceRoot":"","sources":["src/stdio.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAkB,qBAAkB;AAIvD,eAAO,MAAM,iBAAiB,GAAU,YAAY,UAAU,kBAY7D,CAAC"}
package/stdio.js CHANGED
@@ -2,12 +2,14 @@
2
2
  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
+ const options_1 = require("./options.js");
5
6
  const server_1 = require("./server.js");
6
7
  const logger_1 = require("./logger.js");
7
8
  const launchStdioServer = async (mcpOptions) => {
8
9
  const server = await (0, server_1.newMcpServer)({
9
10
  stainlessApiKey: mcpOptions.stainlessApiKey,
10
11
  customInstructionsPath: mcpOptions.customInstructionsPath,
12
+ toolSurface: (0, options_1.toolSurfaceFor)(mcpOptions),
11
13
  });
12
14
  await (0, server_1.initMcpServer)({ server, mcpOptions, stainlessApiKey: mcpOptions.stainlessApiKey });
13
15
  const transport = new stdio_js_1.StdioServerTransport();
package/stdio.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"stdio.js","sourceRoot":"","sources":["src/stdio.ts"],"names":[],"mappings":";;;AAAA,wEAAiF;AAEjF,wCAAuD;AACvD,wCAAqC;AAE9B,MAAM,iBAAiB,GAAG,KAAK,EAAE,UAAsB,EAAE,EAAE;IAChE,MAAM,MAAM,GAAG,MAAM,IAAA,qBAAY,EAAC;QAChC,eAAe,EAAE,UAAU,CAAC,eAAe;QAC3C,sBAAsB,EAAE,UAAU,CAAC,sBAAsB;KAC1D,CAAC,CAAC;IAEH,MAAM,IAAA,sBAAa,EAAC,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC;IAEzF,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,IAAA,kBAAS,GAAE,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;AAClD,CAAC,CAAC;AAXW,QAAA,iBAAiB,qBAW5B"}
1
+ {"version":3,"file":"stdio.js","sourceRoot":"","sources":["src/stdio.ts"],"names":[],"mappings":";;;AAAA,wEAAiF;AACjF,0CAAuD;AACvD,wCAAuD;AACvD,wCAAqC;AAE9B,MAAM,iBAAiB,GAAG,KAAK,EAAE,UAAsB,EAAE,EAAE;IAChE,MAAM,MAAM,GAAG,MAAM,IAAA,qBAAY,EAAC;QAChC,eAAe,EAAE,UAAU,CAAC,eAAe;QAC3C,sBAAsB,EAAE,UAAU,CAAC,sBAAsB;QACzD,WAAW,EAAE,IAAA,wBAAc,EAAC,UAAU,CAAC;KACxC,CAAC,CAAC;IAEH,MAAM,IAAA,sBAAa,EAAC,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC;IAEzF,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,IAAA,kBAAS,GAAE,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;AAClD,CAAC,CAAC;AAZW,QAAA,iBAAiB,qBAY5B"}
package/stdio.mjs CHANGED
@@ -1,10 +1,12 @@
1
1
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
2
+ import { toolSurfaceFor } from "./options.mjs";
2
3
  import { initMcpServer, newMcpServer } from "./server.mjs";
3
4
  import { getLogger } from "./logger.mjs";
4
5
  export const launchStdioServer = async (mcpOptions) => {
5
6
  const server = await newMcpServer({
6
7
  stainlessApiKey: mcpOptions.stainlessApiKey,
7
8
  customInstructionsPath: mcpOptions.customInstructionsPath,
9
+ toolSurface: toolSurfaceFor(mcpOptions),
8
10
  });
9
11
  await initMcpServer({ server, mcpOptions, stainlessApiKey: mcpOptions.stainlessApiKey });
10
12
  const transport = new StdioServerTransport();
package/stdio.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"stdio.mjs","sourceRoot":"","sources":["src/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,qBAAiB;AACvD,OAAO,EAAE,SAAS,EAAE,qBAAiB;AAErC,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,UAAsB,EAAE,EAAE;IAChE,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;QAChC,eAAe,EAAE,UAAU,CAAC,eAAe;QAC3C,sBAAsB,EAAE,UAAU,CAAC,sBAAsB;KAC1D,CAAC,CAAC;IAEH,MAAM,aAAa,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC;IAEzF,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,SAAS,EAAE,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;AAClD,CAAC,CAAC"}
1
+ {"version":3,"file":"stdio.mjs","sourceRoot":"","sources":["src/stdio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAc,cAAc,EAAE,sBAAkB;AACvD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,qBAAiB;AACvD,OAAO,EAAE,SAAS,EAAE,qBAAiB;AAErC,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,UAAsB,EAAE,EAAE;IAChE,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;QAChC,eAAe,EAAE,UAAU,CAAC,eAAe;QAC3C,sBAAsB,EAAE,UAAU,CAAC,sBAAsB;QACzD,WAAW,EAAE,cAAc,CAAC,UAAU,CAAC;KACxC,CAAC,CAAC;IAEH,MAAM,aAAa,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC;IAEzF,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,SAAS,EAAE,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;AAClD,CAAC,CAAC"}