Skip to content

Commit 017ed42

Browse files
committed
fixing mcp timing issue
1 parent 8bf9200 commit 017ed42

2 files changed

Lines changed: 78 additions & 0 deletions

File tree

src/services/publish-service.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,19 @@ async function executePuts(
283283
results
284284
);
285285
}
286+
} else if (tier === 2) {
287+
const { mcpApis, regularTier2 } = await splitMcpApis(
288+
store,
289+
config.sourceDir,
290+
descriptors
291+
);
292+
293+
await publishAndOutput(client, store, context, config, regularTier2, results);
294+
295+
if (mcpApis.length > 0) {
296+
logger.debug(`Publishing ${mcpApis.length} MCP API resource(s) after regular tier 2 resources`);
297+
await publishAndOutput(client, store, context, config, mcpApis, results);
298+
}
286299
} else {
287300
// For tiers 3/4, exclude child resources whose parent is being published
288301
// in tier 2 (publishApi/publishProduct handle their children internally).
@@ -421,6 +434,31 @@ async function splitPoolBackends(
421434
return { poolBackends, regularTier1 };
422435
}
423436

437+
async function splitMcpApis(
438+
store: IArtifactStore,
439+
sourceDir: string,
440+
descriptors: ResourceDescriptor[]
441+
): Promise<{ mcpApis: ResourceDescriptor[]; regularTier2: ResourceDescriptor[] }> {
442+
const mcpApis: ResourceDescriptor[] = [];
443+
const regularTier2: ResourceDescriptor[] = [];
444+
445+
for (const descriptor of descriptors) {
446+
if (descriptor.type === ResourceType.Api) {
447+
const json = await store.readResource(sourceDir, descriptor);
448+
const props = json?.properties as Record<string, unknown> | undefined;
449+
const mcpTools = props?.mcpTools;
450+
if (Array.isArray(mcpTools) && mcpTools.length > 0) {
451+
mcpApis.push(descriptor);
452+
continue;
453+
}
454+
}
455+
456+
regularTier2.push(descriptor);
457+
}
458+
459+
return { mcpApis, regularTier2 };
460+
}
461+
424462
/**
425463
* Publish a single tier of resources in parallel.
426464
*/

tests/unit/services/publish-service.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,46 @@ describe('publish-service', () => {
207207
expect(publishApi).toHaveBeenCalled();
208208
});
209209

210+
it('should publish regular APIs before MCP APIs in tier 2', async () => {
211+
const resources: ResourceDescriptor[] = [
212+
{ type: ResourceType.Api, nameParts: ['src-rest-openapi'] },
213+
{ type: ResourceType.Api, nameParts: ['src-mcp-from-api'] },
214+
];
215+
216+
const client = createMockClient();
217+
const store = createMockStore(resources);
218+
219+
store.readResource.mockImplementation(async (_sourceDir: string, descriptor: ResourceDescriptor) => {
220+
const name = descriptor.nameParts[descriptor.nameParts.length - 1] ?? '';
221+
if (name === 'src-mcp-from-api') {
222+
return { name, properties: { mcpTools: [{ operationId: '/apis/src-rest-openapi/operations/get' }] } };
223+
}
224+
return { name, properties: {} };
225+
});
226+
227+
const apiCallOrder: string[] = [];
228+
vi.mocked(publishApi).mockImplementation(async (_client, _store, _context, descriptor) => {
229+
apiCallOrder.push(descriptor.nameParts[0] ?? '');
230+
return {
231+
descriptor,
232+
status: 'success',
233+
action: 'put',
234+
};
235+
});
236+
237+
const config: PublishConfig = {
238+
service: testContext,
239+
sourceDir: '/source',
240+
dryRun: false,
241+
deleteUnmatched: false,
242+
logLevel: LogLevel.INFO,
243+
};
244+
245+
await runPublish(client, store, config);
246+
247+
expect(apiCallOrder).toEqual(['src-rest-openapi', 'src-mcp-from-api']);
248+
});
249+
210250
it('should call generateDryRunReport in dry-run mode', async () => {
211251
const resources = [
212252
{ type: ResourceType.Tag, nameParts: ['tag1'] },

0 commit comments

Comments
 (0)