Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 119 additions & 0 deletions src/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Agent } from './sdk/agent';
import { Scorer } from './sdk/scorer';
import { NetworkPolicy } from './sdk/network-policy';
import { GatewayConfig } from './sdk/gateway-config';
import { McpConfig } from './sdk/mcp-config';
import { Scenario } from './sdk/scenario';

// Import types used in this file
Expand All @@ -24,6 +25,7 @@ import type { AgentCreateParams, AgentListParams } from './resources/agents';
import type { ScorerCreateParams, ScorerListParams } from './resources/scenarios/scorers';
import type { NetworkPolicyCreateParams, NetworkPolicyListParams } from './resources/network-policies';
import type { GatewayConfigCreateParams, GatewayConfigListParams } from './resources/gateway-configs';
import type { McpConfigCreateParams, McpConfigListParams } from './resources/mcp-configs';
import type { ScenarioListParams } from './resources/scenarios/scenarios';
import { PollingOptions } from './lib/polling';
import * as Shared from './resources/shared';
Expand Down Expand Up @@ -200,6 +202,8 @@ type ContentType = ObjectCreateParams['content_type'];
* - `agent` - {@link AgentOps}
* - `scorer` - {@link ScorerOps}
* - `networkPolicy` - {@link NetworkPolicyOps}
* - `gatewayConfig` - {@link GatewayConfigOps}
* - `mcpConfig` - {@link McpConfigOps}
*
* See the documentation for each Operations class for more details.
*
Expand Down Expand Up @@ -295,6 +299,15 @@ export class RunloopSDK {
*/
public readonly gatewayConfig: GatewayConfigOps;

/**
* **MCP Config Operations** - {@link McpConfigOps} for creating and accessing {@link McpConfig} class instances.
*
* MCP configs define how to connect to upstream MCP (Model Context Protocol) servers. They specify
* the target endpoint and which tools are allowed. Use with devboxes to securely connect to
* MCP servers.
*/
public readonly mcpConfig: McpConfigOps;

/**
* **Scenario Operations** - {@link ScenarioOps} for accessing {@link Scenario} class instances.
*
Expand All @@ -317,6 +330,7 @@ export class RunloopSDK {
this.scorer = new ScorerOps(this.api);
this.networkPolicy = new NetworkPolicyOps(this.api);
this.gatewayConfig = new GatewayConfigOps(this.api);
this.mcpConfig = new McpConfigOps(this.api);
this.scenario = new ScenarioOps(this.api);
}
}
Expand Down Expand Up @@ -1627,6 +1641,108 @@ export class GatewayConfigOps {
}
}

/**
* MCP Config SDK interface for managing MCP configurations.
*
* @category MCP Config
*
* @remarks
* ## Overview
*
* The `McpConfigOps` class provides a high-level abstraction for managing MCP configurations,
* which define how to connect to upstream MCP (Model Context Protocol) servers. MCP configs
* specify the target endpoint and which tools are allowed.
*
* ## Usage
*
* This interface is accessed via {@link RunloopSDK.mcpConfig}. You should construct
* a {@link RunloopSDK} instance and use it from there:
*
* @example
* ```typescript
* const runloop = new RunloopSDK();
* const mcpConfig = await runloop.mcpConfig.create({
* name: 'my-mcp-server',
* endpoint: 'https://mcp.example.com',
* allowed_tools: ['*'],
* });
*
* const info = await mcpConfig.getInfo();
* console.log(`MCP Config: ${info.name}`);
* ```
*/
export class McpConfigOps {
/**
* @private
*/
constructor(private client: RunloopAPI) {}

/**
* Create a new MCP config.
*
* @example
* ```typescript
* const runloop = new RunloopSDK();
* const mcpConfig = await runloop.mcpConfig.create({
* name: 'my-mcp-server',
* endpoint: 'https://mcp.example.com',
* allowed_tools: ['*'],
* description: 'MCP server for my tools',
* });
* ```
*
* @param {McpConfigCreateParams} params - Parameters for creating the MCP config.
* @param {Core.RequestOptions} [options] - Request options.
* @returns {Promise<McpConfig>} A {@link McpConfig} instance.
*/
async create(params: McpConfigCreateParams, options?: Core.RequestOptions): Promise<McpConfig> {
return McpConfig.create(this.client, params, options);
}

/**
* Get an MCP config object by its ID.
*
* @example
* ```typescript
* const runloop = new RunloopSDK();
* const mcpConfig = runloop.mcpConfig.fromId('mcp_1234567890');
* const info = await mcpConfig.getInfo();
* console.log(`MCP Config name: ${info.name}`);
* ```
*
* @param {string} id - The ID of the MCP config.
* @returns {McpConfig} A {@link McpConfig} instance.
*/
fromId(id: string): McpConfig {
return McpConfig.fromId(this.client, id);
}

/**
* List MCP configs with optional filters (paginated).
*
* @example
* ```typescript
* const runloop = new RunloopSDK();
* const configs = await runloop.mcpConfig.list({ limit: 10 });
* console.log(configs.map((c) => c.id));
* ```
*
* @param {McpConfigListParams} [params] - Optional filter parameters.
* @param {Core.RequestOptions} [options] - Request options.
* @returns {Promise<McpConfig[]>} An array of {@link McpConfig} instances.
*/
async list(params?: McpConfigListParams, options?: Core.RequestOptions): Promise<McpConfig[]> {
const result = await this.client.mcpConfigs.list(params, options);
const configs: McpConfig[] = [];

for await (const config of result) {
configs.push(McpConfig.fromId(this.client, config.id));
}

return configs;
}
}

/**
* Scenario SDK interface for managing scenarios.
*
Expand Down Expand Up @@ -1750,6 +1866,7 @@ export declare namespace RunloopSDK {
ScorerOps as ScorerOps,
NetworkPolicyOps as NetworkPolicyOps,
GatewayConfigOps as GatewayConfigOps,
McpConfigOps as McpConfigOps,
ScenarioOps as ScenarioOps,
Devbox as Devbox,
Blueprint as Blueprint,
Expand All @@ -1759,6 +1876,7 @@ export declare namespace RunloopSDK {
Scorer as Scorer,
NetworkPolicy as NetworkPolicy,
GatewayConfig as GatewayConfig,
McpConfig as McpConfig,
Scenario as Scenario,
};
}
Expand All @@ -1775,6 +1893,7 @@ export {
Agent,
Scorer,
NetworkPolicy,
McpConfig,
Execution,
ExecutionResult,
Scenario,
Expand Down
1 change: 1 addition & 0 deletions src/sdk/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ export { ExecutionResult } from './execution-result';
export { Scorer } from './scorer';
export { NetworkPolicy } from './network-policy';
export { GatewayConfig } from './gateway-config';
export { McpConfig } from './mcp-config';
export { ScenarioRun } from './scenario-run';
export { Scenario, type ScenarioRunParams } from './scenario';
158 changes: 158 additions & 0 deletions src/sdk/mcp-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import { Runloop } from '../index';
import type * as Core from '../core';
import type { McpConfigView, McpConfigCreateParams, McpConfigUpdateParams } from '../resources/mcp-configs';

/**
* Object-oriented interface for working with MCP Configs.
*
* @category MCP Config
*
* @remarks
* ## Overview
*
* The `McpConfig` class provides a high-level, object-oriented API for managing MCP configurations.
* MCP configs define how to connect to upstream MCP (Model Context Protocol) servers, specifying the
* target endpoint and which tools are allowed. They can be used with devboxes to securely connect
* to MCP servers.
*
* ## Quickstart
*
* ```typescript
* import { RunloopSDK } from '@runloop/api-client-ts';
*
* const runloop = new RunloopSDK();
* const mcpConfig = await runloop.mcpConfig.create({
* name: 'my-mcp-server',
* endpoint: 'https://mcp.example.com',
* allowed_tools: ['*'],
* });
*
* const info = await mcpConfig.getInfo();
* console.log(`MCP Config: ${info.name}`);
* ```
*/
export class McpConfig {
private client: Runloop;
private _id: string;

private constructor(client: Runloop, id: string) {
this.client = client;
this._id = id;
}

/**
* Create a new McpConfig with the specified configuration.
* This is the recommended way to create an MCP config.
*
* See the {@link McpConfigOps.create} method for calling this
* @private
*
* @example
* ```typescript
* const runloop = new RunloopSDK();
* const mcpConfig = await runloop.mcpConfig.create({
* name: 'my-mcp-server',
* endpoint: 'https://mcp.example.com',
* allowed_tools: ['*'],
* description: 'MCP server for my tools',
* });
* ```
*
* @param {Runloop} client - The Runloop client instance
* @param {McpConfigCreateParams} params - Parameters for creating the MCP config
* @param {Core.RequestOptions} [options] - Request options
* @returns {Promise<McpConfig>} A {@link McpConfig} instance
*/
static async create(
client: Runloop,
params: McpConfigCreateParams,
options?: Core.RequestOptions,
): Promise<McpConfig> {
const configData = await client.mcpConfigs.create(params, options);
return new McpConfig(client, configData.id);
}

/**
* Create a McpConfig instance by ID without retrieving from API.
* Use getInfo() to fetch the actual data when needed.
*
* See the {@link McpConfigOps.fromId} method for calling this
* @private
*
* @example
* ```typescript
* const runloop = new RunloopSDK();
* const mcpConfig = runloop.mcpConfig.fromId('mcp_1234567890');
* const info = await mcpConfig.getInfo();
* console.log(`MCP Config name: ${info.name}`);
* ```
*
* @param {Runloop} client - The Runloop client instance
* @param {string} id - The MCP config ID
* @returns {McpConfig} A {@link McpConfig} instance
*/
static fromId(client: Runloop, id: string): McpConfig {
return new McpConfig(client, id);
}

/**
* Get the MCP config ID.
* @returns {string} The MCP config ID
*/
get id(): string {
return this._id;
}

/**
* Get the complete MCP config data from the API.
*
* @example
* ```typescript
* const info = await mcpConfig.getInfo();
* console.log(`MCP Config: ${info.name}, endpoint: ${info.endpoint}`);
* ```
*
* @param {Core.RequestOptions} [options] - Request options
* @returns {Promise<McpConfigView>} The MCP config data
*/
async getInfo(options?: Core.RequestOptions): Promise<McpConfigView> {
return this.client.mcpConfigs.retrieve(this._id, options);
}

/**
* Update an existing McpConfig. All fields are optional.
*
* @example
* ```typescript
* const updated = await mcpConfig.update({
* name: 'updated-mcp-name',
* description: 'Updated description',
* });
* ```
*
* @param {McpConfigUpdateParams} params - Parameters for updating the MCP config
* @param {Core.RequestOptions} [options] - Request options
* @returns {Promise<McpConfigView>} The updated MCP config data
*/
async update(params: McpConfigUpdateParams, options?: Core.RequestOptions): Promise<McpConfigView> {
return this.client.mcpConfigs.update(this._id, params, options);
}

/**
* Delete this MCP config. This action is irreversible.
*
* @private
* See the {@link McpConfigOps.delete} method for calling this
*
* @example
* ```typescript
* await mcpConfig.delete();
* ```
*
* @param {Core.RequestOptions} [options] - Request options
* @returns {Promise<McpConfigView>} The deleted MCP config data
*/
async delete(options?: Core.RequestOptions): Promise<McpConfigView> {
return this.client.mcpConfigs.delete(this._id, {}, options);
}
}
Loading
Loading