1- import type { RouteContext } from './route-context.js' ;
1+ import { ConfigIO } from '../../../../../lib' ;
2+ import { mcpCallTool , mcpInitSession , mcpListTools } from '../../../../aws/agentcore' ;
3+ import { resolveInvokeTarget } from '../../../../commands/invoke/resolve' ;
4+ import { type RouteContext , parseRequestUrl } from './route-context.js' ;
25import type { IncomingMessage , ServerResponse } from 'http' ;
36
47export async function handleMcpProxy (
@@ -7,6 +10,11 @@ export async function handleMcpProxy(
710 res : ServerResponse ,
811 origin ?: string
912) : Promise < void > {
13+ const { param } = parseRequestUrl ( req ) ;
14+ if ( param ( 'target' ) === 'deployed' ) {
15+ return handleDeployedMcpProxy ( ctx , req , res , origin ) ;
16+ }
17+
1018 ctx . setCorsHeaders ( res , origin ) ;
1119
1220 const raw = await ctx . readBody ( req ) ;
@@ -80,3 +88,135 @@ export async function handleMcpProxy(
8088 res . writeHead ( 200 , { 'Content-Type' : 'application/json' } ) ;
8189 res . end ( JSON . stringify ( { success : true , result, sessionId : responseSessionId } ) ) ;
8290}
91+
92+ async function handleDeployedMcpProxy (
93+ ctx : RouteContext ,
94+ req : IncomingMessage ,
95+ res : ServerResponse ,
96+ origin ?: string
97+ ) : Promise < void > {
98+ const { configRoot } = ctx . options ;
99+ if ( ! configRoot ) {
100+ ctx . setCorsHeaders ( res , origin ) ;
101+ res . writeHead ( 404 , { 'Content-Type' : 'application/json' } ) ;
102+ res . end ( JSON . stringify ( { success : false , error : 'No agentcore project found' } ) ) ;
103+ return ;
104+ }
105+
106+ const raw = await ctx . readBody ( req ) ;
107+ let parsed : {
108+ agentName ?: string ;
109+ targetName ?: string ;
110+ body ?: Record < string , unknown > ;
111+ sessionId ?: string ;
112+ } ;
113+ try {
114+ parsed = JSON . parse ( raw ) as typeof parsed ;
115+ } catch {
116+ ctx . setCorsHeaders ( res , origin ) ;
117+ res . writeHead ( 400 , { 'Content-Type' : 'application/json' } ) ;
118+ res . end ( JSON . stringify ( { success : false , error : 'Invalid JSON' } ) ) ;
119+ return ;
120+ }
121+
122+ const { agentName, targetName, body, sessionId } = parsed ;
123+
124+ if ( ! body ) {
125+ ctx . setCorsHeaders ( res , origin ) ;
126+ res . writeHead ( 400 , { 'Content-Type' : 'application/json' } ) ;
127+ res . end ( JSON . stringify ( { success : false , error : 'body is required' } ) ) ;
128+ return ;
129+ }
130+
131+ const configIO = new ConfigIO ( { baseDir : configRoot } ) ;
132+ let project ;
133+ let deployedState ;
134+ let awsTargets ;
135+ try {
136+ project = await configIO . readProjectSpec ( ) ;
137+ deployedState = await configIO . readDeployedState ( ) ;
138+ awsTargets = await configIO . readAWSDeploymentTargets ( ) ;
139+ } catch ( err ) {
140+ ctx . setCorsHeaders ( res , origin ) ;
141+ res . writeHead ( 500 , { 'Content-Type' : 'application/json' } ) ;
142+ res . end (
143+ JSON . stringify ( {
144+ success : false ,
145+ error : `Failed to load config: ${ err instanceof Error ? err . message : String ( err ) } ` ,
146+ } )
147+ ) ;
148+ return ;
149+ }
150+
151+ const resolved = await resolveInvokeTarget ( {
152+ project,
153+ deployedState,
154+ awsTargets,
155+ agentName,
156+ targetName,
157+ sessionId,
158+ configIO,
159+ } ) ;
160+
161+ if ( ! resolved . success ) {
162+ ctx . setCorsHeaders ( res , origin ) ;
163+ res . writeHead ( 400 , { 'Content-Type' : 'application/json' } ) ;
164+ res . end ( JSON . stringify ( { success : false , error : resolved . error . message } ) ) ;
165+ return ;
166+ }
167+
168+ const mcpOpts = {
169+ region : resolved . region ,
170+ runtimeArn : resolved . runtimeArn ,
171+ bearerToken : resolved . bearerToken ,
172+ mcpSessionId : sessionId ,
173+ } ;
174+
175+ const method = ( body as { method ?: string } ) . method ;
176+
177+ try {
178+ if ( method === 'initialize' ) {
179+ const mcpSessionId = await mcpInitSession ( mcpOpts ) ;
180+ ctx . setCorsHeaders ( res , origin ) ;
181+ res . writeHead ( 200 , { 'Content-Type' : 'application/json' } ) ;
182+ res . end ( JSON . stringify ( { success : true , result : { jsonrpc : '2.0' , result : { } } , sessionId : mcpSessionId } ) ) ;
183+ } else if ( method === 'tools/list' ) {
184+ const result = await mcpListTools ( mcpOpts ) ;
185+ ctx . setCorsHeaders ( res , origin ) ;
186+ res . writeHead ( 200 , { 'Content-Type' : 'application/json' } ) ;
187+ res . end ( JSON . stringify ( { success : true , result : { jsonrpc : '2.0' , result } } ) ) ;
188+ } else if ( method === 'tools/call' ) {
189+ const params = ( body as { params ?: { name ?: string ; arguments ?: Record < string , unknown > } } ) . params ;
190+ if ( ! params ?. name ) {
191+ ctx . setCorsHeaders ( res , origin ) ;
192+ res . writeHead ( 400 , { 'Content-Type' : 'application/json' } ) ;
193+ res . end ( JSON . stringify ( { success : false , error : 'tools/call requires params.name' } ) ) ;
194+ return ;
195+ }
196+ const response = await mcpCallTool ( mcpOpts , params . name , params . arguments ?? { } ) ;
197+ ctx . setCorsHeaders ( res , origin ) ;
198+ res . writeHead ( 200 , { 'Content-Type' : 'application/json' } ) ;
199+ res . end (
200+ JSON . stringify ( {
201+ success : true ,
202+ result : { jsonrpc : '2.0' , result : { content : [ { type : 'text' , text : response } ] } } ,
203+ } )
204+ ) ;
205+ } else {
206+ ctx . setCorsHeaders ( res , origin ) ;
207+ res . writeHead ( 400 , { 'Content-Type' : 'application/json' } ) ;
208+ res . end ( JSON . stringify ( { success : false , error : `Unsupported MCP method: ${ method } ` } ) ) ;
209+ }
210+ } catch ( err ) {
211+ ctx . setCorsHeaders ( res , origin ) ;
212+ if ( ! res . headersSent ) {
213+ res . writeHead ( 502 , { 'Content-Type' : 'application/json' } ) ;
214+ }
215+ res . end (
216+ JSON . stringify ( {
217+ success : false ,
218+ error : `MCP invoke failed: ${ err instanceof Error ? err . message : String ( err ) } ` ,
219+ } )
220+ ) ;
221+ }
222+ }
0 commit comments