-
Couldn't load subscription status.
- Fork 2
feat: introduce fetchTools
#114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: introduce fetchTools
#114
Conversation
commit: |
There was a problem hiding this 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. |
Copilot
AI
Oct 8, 2025
There was a problem hiding this comment.
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.'
| } 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. |
| 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; | ||
| } |
Copilot
AI
Oct 8, 2025
There was a problem hiding this comment.
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.
There was a problem hiding this 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'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(), |
There was a problem hiding this comment.
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'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>
fetchTools
a0b1003 to
b6e4146
Compare
| 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; | ||
| } |
There was a problem hiding this comment.
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>; |
There was a problem hiding this comment.
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
This reverts commit 0797d5e.
9409b6f to
08d1599
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
Summary
StackOneToolSet.fetchTools()so tools execute via the RPC client without local specsfetchTools) and add an example covering real-world executionstackone.fetchTools({ accountIDs: [...] })) so callers can scope MCP catalog fetchesTesting