Files
ai-inference/src/mcp.ts

142 lines
3.5 KiB
TypeScript
Raw Normal View History

2025-07-16 00:12:41 +00:00
import * as core from '@actions/core'
import {Client} from '@modelcontextprotocol/sdk/client/index.js'
import {StreamableHTTPClientTransport} from '@modelcontextprotocol/sdk/client/streamableHttp.js'
2025-07-16 00:12:41 +00:00
export interface ToolResult {
tool_call_id: string
role: 'tool'
name: string
content: string
}
2025-07-16 02:19:49 +00:00
export interface MCPTool {
type: 'function'
function: {
name: string
description?: string
parameters?: Record<string, unknown>
}
}
export interface ToolCall {
id: string
type: string
function: {
name: string
arguments: string
}
}
export interface GitHubMCPClient {
2025-07-16 00:12:41 +00:00
client: Client
2025-07-16 02:19:49 +00:00
tools: Array<MCPTool>
2025-07-16 00:12:41 +00:00
}
/**
2025-07-16 02:19:49 +00:00
* Connect to the GitHub MCP server and retrieve available tools
2025-07-16 00:12:41 +00:00
*/
export async function connectToGitHubMCP(token: string, toolsets?: string): Promise<GitHubMCPClient | null> {
2025-07-16 02:19:49 +00:00
const githubMcpUrl = 'https://api.githubcopilot.com/mcp/'
2025-07-16 00:12:41 +00:00
core.info('Connecting to GitHub MCP server...')
const headers: Record<string, string> = {
Authorization: `Bearer ${token}`,
'X-MCP-Readonly': 'true',
}
// Add toolsets header if specified
if (toolsets && toolsets.trim() !== '') {
headers['X-MCP-Toolsets'] = toolsets
core.info(`Using GitHub MCP toolsets: ${toolsets}`)
} else {
core.info('Using default GitHub MCP toolsets')
}
2025-07-16 02:19:49 +00:00
const transport = new StreamableHTTPClientTransport(new URL(githubMcpUrl), {
2025-07-16 00:12:41 +00:00
requestInit: {
headers,
},
2025-07-16 00:12:41 +00:00
})
const client = new Client({
name: 'ai-inference-action',
version: '1.0.0',
transport,
2025-07-16 00:12:41 +00:00
})
try {
await client.connect(transport)
} catch (mcpError) {
2025-07-16 02:19:49 +00:00
core.warning(`Failed to connect to GitHub MCP server: ${mcpError}`)
2025-07-16 00:12:41 +00:00
return null
}
2025-07-16 02:19:49 +00:00
core.info('Successfully connected to GitHub MCP server')
2025-07-16 00:12:41 +00:00
const toolsResponse = await client.listTools()
core.info(`Retrieved ${toolsResponse.tools?.length || 0} tools from GitHub MCP server`)
2025-07-16 00:12:41 +00:00
2025-07-16 02:19:49 +00:00
// Map GitHub MCP tools → Azure AI Inference tool definitions
const tools = (toolsResponse.tools || []).map(t => ({
2025-07-16 02:19:49 +00:00
type: 'function' as const,
2025-07-16 00:12:41 +00:00
function: {
name: t.name,
description: t.description,
parameters: t.inputSchema,
},
2025-07-16 00:12:41 +00:00
}))
2025-07-16 02:19:49 +00:00
core.info(`Mapped ${tools.length} GitHub MCP tools for Azure AI Inference`)
2025-07-16 00:12:41 +00:00
return {client, tools}
2025-07-16 00:12:41 +00:00
}
/**
2025-07-16 02:19:49 +00:00
* Execute a single tool call via GitHub MCP
2025-07-16 00:12:41 +00:00
*/
export async function executeToolCall(githubMcpClient: Client, toolCall: ToolCall): Promise<ToolResult> {
core.info(`Executing GitHub MCP tool: ${toolCall.function.name} with args: ${toolCall.function.arguments}`)
2025-07-16 00:12:41 +00:00
try {
const args = JSON.parse(toolCall.function.arguments)
2025-07-16 02:19:49 +00:00
const result = await githubMcpClient.callTool({
2025-07-16 00:12:41 +00:00
name: toolCall.function.name,
arguments: args,
2025-07-16 00:12:41 +00:00
})
2025-07-16 02:19:49 +00:00
core.info(`GitHub MCP tool ${toolCall.function.name} executed successfully`)
2025-07-16 00:12:41 +00:00
return {
tool_call_id: toolCall.id,
role: 'tool',
name: toolCall.function.name,
content: JSON.stringify(result.content),
2025-07-16 00:12:41 +00:00
}
} catch (toolError) {
core.warning(`Failed to execute GitHub MCP tool ${toolCall.function.name}: ${toolError}`)
2025-07-16 00:12:41 +00:00
return {
tool_call_id: toolCall.id,
role: 'tool',
name: toolCall.function.name,
content: `Error: ${toolError}`,
2025-07-16 00:12:41 +00:00
}
}
}
/**
2025-07-16 02:19:49 +00:00
* Execute all tool calls from a response via GitHub MCP
2025-07-16 00:12:41 +00:00
*/
export async function executeToolCalls(githubMcpClient: Client, toolCalls: ToolCall[]): Promise<ToolResult[]> {
2025-07-16 00:12:41 +00:00
const toolResults: ToolResult[] = []
for (const toolCall of toolCalls) {
2025-07-16 02:19:49 +00:00
const result = await executeToolCall(githubMcpClient, toolCall)
2025-07-16 00:12:41 +00:00
toolResults.push(result)
}
return toolResults
}