Skip to content

Conversation

@ryoppippi
Copy link
Contributor

@ryoppippi ryoppippi commented Oct 8, 2025

Summary

  • wire StackOne MCP catalog into StackOneToolSet.fetchTools() so tools execute via the RPC client without local specs
  • add richer tool abstractions (meta tools, execution metadata) and Orama-backed search to support dynamic discovery
  • document live-catalog usage (fetchTools) and add an example covering real-world execution
  • note that when used in AI SDK flows, these tools execute by delegating to the StackOne TypeScript SDK's RPC client
  • TODO documented: expose filters for accounts/providers/actions (e.g., stackone.fetchTools({ accountIDs: [...] })) so callers can scope MCP catalog fetches

Testing

  • bun test
  • bun test examples/examples.spec.ts
  • bun run typecheck

Copilot AI review requested due to automatic review settings October 8, 2025 15:08
@pkg-pr-new
Copy link

pkg-pr-new bot commented Oct 8, 2025

Open in StackBlitz

npm i https://pkg.pr.new/StackOneHQ/stackone-ai-node/@stackone/ai@114

commit: 08d1599

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces MCP-backed dynamic tool discovery to enable RPC actions generated from external catalogs. The implementation adds support for different execution styles (HTTP, RPC, local) through discriminated unions and includes enhanced metadata exposure for AI SDK tools.

  • Refactors ExecuteConfig into discriminated union (HttpExecuteConfig, RpcExecuteConfig, LocalExecuteConfig)
  • Adds MCP client integration for dynamic tool fetching with RPC execution support
  • Introduces execution metadata exposure controls for AI SDK tool conversion

Reviewed Changes

Copilot reviewed 16 out of 17 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/types.ts Defines discriminated union for execution configurations and tool metadata types
src/toolsets/base.ts Implements MCP tool fetching and RPC-backed tool creation with StackOne client integration
src/tool.ts Updates BaseTool to support multiple execution types and metadata exposure controls
src/openapi/parser.ts Updates OpenAPI parser to use new HttpExecuteConfig format
src/mcp.ts Adds MCP client factory with proper resource cleanup
Various test files Updates test fixtures to use new execution config format

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

path: 'path',
query: 'query',
},
} as const satisfies RpcExecuteConfig; // Mirrors StackOne RPC payload layout so metadata/debug stays in sync.
Copy link

Copilot AI Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The comment explains the purpose but could be clearer. Consider: 'Configuration mirrors StackOne RPC payload structure to maintain metadata and debug information compatibility.'

Suggested change
} as const satisfies RpcExecuteConfig; // Mirrors StackOne RPC payload layout so metadata/debug stays in sync.
} as const satisfies RpcExecuteConfig; // Configuration mirrors StackOne RPC payload structure to maintain metadata and debug information compatibility.

Copilot uses AI. Check for mistakes.
Comment on lines +440 to +452
private extractRecord(
params: JsonDict,
key: 'body' | 'headers' | 'path' | 'query'
): JsonDict | undefined {
const value = params[key];
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
return value as JsonDict;
}
return undefined;
}
Copy link

Copilot AI Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method performs type checking and casting that could be more robust. Consider validating that the object has only string keys or use a more specific type guard function.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cubic analysis

1 issue found across 17 files

Prompt for AI agents (all 1 issues)

Understand the root cause of the following 1 issues and fix them.


<file name="src/tool.ts">

<violation number="1" location="src/tool.ts:60">
Rule violated: **Flag Security Vulnerabilities**

createExecutionMetadata now exposes the tool&#39;s live headers (e.g., Authorization tokens) via the AI SDK execution metadata, leaking credentials to downstream consumers. Remove the sensitive header values from the metadata to prevent secret exposure.</violation>
</file>

Linked issue analysis

Linked issue: ENG-11034: Add Dynamic tool fetching via MCP in our SDK

Status Acceptance criteria Notes
SDK can use MCP servers under the hood to fetch tools dynamically Added createMCPClient and integrated in ToolSet base
Provide examples/docs showing how to use MCP-backed dynamic tools README and examples reference MCP dynamic tool usage

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.


return {
config,
headers: this.getHeaders(),
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rule violated: Flag Security Vulnerabilities

createExecutionMetadata now exposes the tool's live headers (e.g., Authorization tokens) via the AI SDK execution metadata, leaking credentials to downstream consumers. Remove the sensitive header values from the metadata to prevent secret exposure.

Prompt for AI agents
Address the following comment on src/tool.ts at line 60:

<comment>createExecutionMetadata now exposes the tool&#39;s live headers (e.g., Authorization tokens) via the AI SDK execution metadata, leaking credentials to downstream consumers. Remove the sensitive header values from the metadata to prevent secret exposure.</comment>

<file context>
@@ -21,8 +24,42 @@ export class BaseTool {
+
+    return {
+      config,
+      headers: this.getHeaders(),
+    };
+  }
</file context>
Fix with Cubic

@ryoppippi ryoppippi enabled auto-merge (squash) October 8, 2025 15:26
@ryoppippi ryoppippi changed the title feat: introduce MCP-backed dynamic tools feat: introduce fetchTools Oct 8, 2025
@ryoppippi ryoppippi force-pushed the ENG-11034-add-dynamic-tool-fetching-via-mcp-in-our-sdk branch from a0b1003 to b6e4146 Compare October 8, 2025 15:55
Comment on lines +16 to +48
async function createMockMcpServer(tools: MockTool[]) {
const mcp = new McpServer({ name: 'test-mcp', version: '1.0.0' });

for (const tool of tools) {
mcp.registerTool(
tool.name,
{
description: tool.description,
inputSchema: tool.shape,
},
async ({ params }) => ({
content: [],
structuredContent: params.arguments ?? {},
_meta: undefined,
})
);
}

const app = new Hono();
app.all('/mcp', async (c) => {
const transport = new StreamableHTTPTransport();
await mcp.connect(transport);
return transport.handleRequest(c);
});

const server = Bun.serve({ port: 0, fetch: app.fetch });
const origin = server.url.toString().replace(/\/$/, '');

return {
origin,
close: () => server.stop(),
} as const;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create dummy mcp server with hono/mcp

transport: StreamableHTTPClientTransport;

/** cleanup client and transport */
[Symbol.asyncDispose](): Promise<void>;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

close mcp client with await using

@ryoppippi ryoppippi requested a review from a team as a code owner October 8, 2025 16:07
@ryoppippi ryoppippi force-pushed the ENG-11034-add-dynamic-tool-fetching-via-mcp-in-our-sdk branch from 9409b6f to 08d1599 Compare October 8, 2025 16:08
Copy link
Contributor

@NicolasBelissent NicolasBelissent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@ryoppippi ryoppippi merged commit ef5efc1 into main Oct 8, 2025
6 checks passed
@ryoppippi ryoppippi deleted the ENG-11034-add-dynamic-tool-fetching-via-mcp-in-our-sdk branch October 8, 2025 16:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants