@@ -3,7 +3,7 @@ import type { AddressInfo } from 'node:net';
33import express from 'express' ;
44import type { Express } from 'express' ;
55import { afterAll , beforeAll , describe , expect , it } from 'vitest' ;
6- import { getArtifact , fetchProjectFile } from '../src/mcp.js' ;
6+ import { getArtifact , fetchProjectFile , handleMcpToolCall } from '../src/mcp.js' ;
77
88// A minimal mock of the daemon's project file endpoints. Tests control
99// the file list and per-file response via the opts object.
@@ -178,3 +178,54 @@ describe('getArtifact truncated: true when per-file content-length pre-check fir
178178 expect ( body . files . length ) . toBe ( 1 ) ;
179179 } ) ;
180180} ) ;
181+
182+ describe ( 'public MCP get_artifact active context defaults' , ( ) => {
183+ let server : http . Server ;
184+ let baseUrl : string ;
185+
186+ beforeAll ( async ( ) => {
187+ const app = express ( ) ;
188+ app . get ( '/api/active' , ( _req , res ) =>
189+ res . json ( {
190+ active : true ,
191+ projectId : 'active-project' ,
192+ projectName : 'Active Project' ,
193+ fileName : 'landing.html' ,
194+ ageMs : 50 ,
195+ } ) ,
196+ ) ;
197+ app . get ( '/api/projects/:id' , ( _req , res ) =>
198+ res . json ( {
199+ project : {
200+ id : 'active-project' ,
201+ name : 'Active Project' ,
202+ metadata : { entryFile : 'index.html' } ,
203+ } ,
204+ } ) ,
205+ ) ;
206+ app . get ( '/api/projects/:id/raw/*splat' , ( req , res ) => {
207+ expect ( req . params . id ) . toBe ( 'active-project' ) ;
208+ expect ( req . params . splat ) . toEqual ( [ 'landing.html' ] ) ;
209+ res . set ( { 'content-type' : 'text/html' } ) . send ( '<!doctype html><h1>Active artifact</h1>' ) ;
210+ } ) ;
211+ const r = await startServer ( app ) ;
212+ server = r . server ;
213+ baseUrl = r . baseUrl ;
214+ } ) ;
215+
216+ afterAll ( ( ) => new Promise ( ( resolve ) => server . close ( resolve ) ) ) ;
217+
218+ it ( 'uses the active file ahead of metadata.entryFile when project and entry are omitted' , async ( ) => {
219+ const result = await handleMcpToolCall ( baseUrl , 'get_artifact' , { include : 'shallow' } ) ;
220+ const body = parseArtifactBody ( firstText ( result . content ) ) as ArtifactBody & {
221+ entryFile ?: string ;
222+ usedActiveContext ?: { projectId ?: string ; fileName ?: string } ;
223+ } ;
224+ expect ( body . entryFile ) . toBe ( 'landing.html' ) ;
225+ expect ( body . files ) . toHaveLength ( 1 ) ;
226+ expect ( body . usedActiveContext ) . toMatchObject ( {
227+ projectId : 'active-project' ,
228+ fileName : 'landing.html' ,
229+ } ) ;
230+ } ) ;
231+ } ) ;
0 commit comments