fix(mcp-actions-backend): return structured content and remove markdown formatting in tool responses
This change aligns the MCP tool execution responses with the specification by returning plain text in the 'content' array and providing the raw JSON in a new 'structuredContent' field. It also removes the unnecessary Markdown code block formatting that was previously added to tool results. Fixes #34052 Signed-off-by: Love Kumar Chauhan <lovechauhan6564@gmail.com> Co-authored-by: benjdlambert <3645856+benjdlambert@users.noreply.github.com> Signed-off-by: benjdlambert <ben@blam.sh>
This commit is contained in:
committed by
benjdlambert
parent
381cf2ae10
commit
ca8951ae87
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-mcp-actions-backend': patch
|
||||
---
|
||||
|
||||
Fixed an issue where actions returned Markdown-formatted JSON instead of plain JSON and a `structuredContent` field for model context protocol responses.
|
||||
@@ -140,7 +140,7 @@ Allows multiple panels to be open simultaneously.
|
||||
<Snippet
|
||||
align="center"
|
||||
py={4}
|
||||
height="auto"
|
||||
height={280}
|
||||
preview={<GroupMultipleOpen />}
|
||||
code={groupMultipleOpenSnippet}
|
||||
/>
|
||||
|
||||
@@ -135,6 +135,10 @@ When errors are thrown from MCP actions, the backend will handle and surface err
|
||||
|
||||
See [Backstage Errors](https://backstage.io/docs/reference/errors/) for a full list of supported errors.
|
||||
|
||||
### Response Format
|
||||
|
||||
Tool execution results are returned in a format compliant with the MCP specification, including both a plain-text representation in the `content` array and the raw JSON result in the `structuredContent` field. This ensures that AI clients can process the data either as text or as structured data for more precise tool use.
|
||||
|
||||
When writing MCP tools, use the appropriate error from `@backstage/errors` when applicable:
|
||||
|
||||
```ts
|
||||
|
||||
@@ -216,13 +216,10 @@ describe('McpService', () => {
|
||||
expect(result.content).toEqual([
|
||||
{
|
||||
type: 'text',
|
||||
text: [
|
||||
'```json',
|
||||
JSON.stringify({ output: 'test' }, null, 2),
|
||||
'```',
|
||||
].join('\n'),
|
||||
text: JSON.stringify({ output: 'test' }),
|
||||
},
|
||||
]);
|
||||
expect((result as any).structuredContent).toEqual({ output: 'test' });
|
||||
|
||||
const histogram = mockMetrics.createHistogram.mock.results[0]?.value;
|
||||
expect(histogram.record).toHaveBeenCalledTimes(1);
|
||||
|
||||
@@ -135,7 +135,6 @@ export class McpService {
|
||||
const server = new McpServer(
|
||||
{
|
||||
name: serverConfig?.name ?? 'backstage',
|
||||
// TODO: this version will most likely change in the future.
|
||||
version,
|
||||
...(serverConfig?.description && {
|
||||
description: serverConfig.description,
|
||||
@@ -159,9 +158,6 @@ export class McpService {
|
||||
return {
|
||||
tools: actions.map(action => ({
|
||||
inputSchema: action.schema.input,
|
||||
// todo(blam): this is unfortunately not supported by most clients yet.
|
||||
// When this is provided you need to provide structuredContent instead.
|
||||
// outputSchema: action.schema.output,
|
||||
name: this.getToolName(action),
|
||||
description: action.description,
|
||||
annotations: {
|
||||
@@ -238,9 +234,6 @@ export class McpService {
|
||||
credentials,
|
||||
});
|
||||
|
||||
// Record the structured action output directly rather than the
|
||||
// CallToolResult envelope below, which wraps an already-
|
||||
// stringified markdown-fenced JSON block.
|
||||
if (this.captureToolPayloads) {
|
||||
span.setAttribute(
|
||||
'gen_ai.tool.call.result',
|
||||
@@ -249,19 +242,13 @@ export class McpService {
|
||||
}
|
||||
|
||||
return {
|
||||
// todo(blam): unfortunately structuredContent is not supported by most clients yet.
|
||||
// so the validation for the output happens in the default actions registry
|
||||
// and we return it as json text instead for now.
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: [
|
||||
'```json',
|
||||
JSON.stringify(output, null, 2),
|
||||
'```',
|
||||
].join('\n'),
|
||||
text: JSON.stringify(output),
|
||||
},
|
||||
],
|
||||
structuredContent: output,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user