Skip to content

feat: introduce fetchTools - #114

Merged
ryoppippi merged 22 commits into
mainfrom
ENG-11034-add-dynamic-tool-fetching-via-mcp-in-our-sdk
Oct 8, 2025
Merged

feat: introduce fetchTools#114
ryoppippi merged 22 commits into
mainfrom
ENG-11034-add-dynamic-tool-fetching-via-mcp-in-our-sdk

Conversation

@ryoppippi

@ryoppippiryoppippi commented Oct 8, 2025

Copy link
Copy Markdown
Contributor

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

CopilotAI review requested due to automatic review settings October 8, 2025 15:08
@pkg-pr-new

pkg-pr-newBot commented Oct 8, 2025

Copy link
Copy Markdown

Open in StackBlitz

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

commit: 08d1599

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

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
FileDescription
src/types.tsDefines discriminated union for execution configurations and tool metadata types
src/toolsets/base.tsImplements MCP tool fetching and RPC-backed tool creation with StackOne client integration
src/tool.tsUpdates BaseTool to support multiple execution types and metadata exposure controls
src/openapi/parser.tsUpdates OpenAPI parser to use new HttpExecuteConfig format
src/mcp.tsAdds MCP client factory with proper resource cleanup
Various test filesUpdates 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.

Comment threadsrc/toolsets/base.ts
path: 'path',
query: 'query',
},
} as const satisfies RpcExecuteConfig; // Mirrors StackOne RPC payload layout so metadata/debug stays in sync.

CopilotAIOct 8, 2025

Copy link

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
}asconstsatisfiesRpcExecuteConfig;// Mirrors StackOne RPC payload layout so metadata/debug stays in sync.
}asconstsatisfiesRpcExecuteConfig;// Configuration mirrors StackOne RPC payload structure to maintain metadata and debug information compatibility.

Copilot uses AI. Check for mistakes.
Comment threadsrc/toolsets/base.ts
Comment on lines +440 to +449
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;
}

CopilotAIOct 8, 2025

Copy link

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.
Comment threadsrc/tool.ts
Comment threadsrc/openapi/parser.ts

@cubic-dev-aicubic-dev-aiBot left a comment

Copy link
Copy Markdown
Contributor

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

StatusAcceptance criteriaNotes
SDK can use MCP servers under the hood to fetch tools dynamicallyAdded createMCPClient and integrated in ToolSet base
Provide examples/docs showing how to use MCP-backed dynamic toolsREADME 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.

Comment threadsrc/tool.ts

return {
config,
headers: this.getHeaders(),

@cubic-dev-aicubic-dev-aiBotOct 8, 2025

Copy link
Copy Markdown
Contributor

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
@ryoppippiryoppippi changed the title feat: introduce MCP-backed dynamic toolsfeat: introduce fetchToolsOct 8, 2025
@ryoppippi
ryoppippiforce-pushed the ENG-11034-add-dynamic-tool-fetching-via-mcp-in-our-sdk branch from a0b1003 to b6e4146CompareOctober 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
Copy Markdown
ContributorAuthor

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

Comment threadsrc/mcp.ts
transport: StreamableHTTPClientTransport;

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

Copy link
Copy Markdown
ContributorAuthor

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 ownerOctober 8, 2025 16:07
@ryoppippi
ryoppippiforce-pushed the ENG-11034-add-dynamic-tool-fetching-via-mcp-in-our-sdk branch from 9409b6f to 08d1599CompareOctober 8, 2025 16:08

@NicolasBelissentNicolasBelissent left a comment

Copy link
Copy Markdown
Contributor

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 mainOct 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
@github-actionsgithub-actionsBot mentioned this pull request Oct 8, 2025
Sign up for freeto 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.

3 participants

@ryoppippi@NicolasBelissent