Skip to content

Commit b7c1428

Browse files
ochafikclaude
andcommitted
Add outputType parameter to zip tool (inlined / resource link / resource)
This change ports the enhancements from PR #2831 in the modelcontextprotocol/servers repository to the example-remote-server codebase. The zip tool now supports three output formats via the 'outputType' parameter: 1. 'inlinedResourceLink' (default) - Returns a resource_link with a data URI (the original behavior, most efficient for small files) 2. 'resourceLink' - Returns a link to a resource stored in a transient map, allowing clients to read the resource later via ReadResource requests 3. 'resource' - Returns the full resource object directly inline This demonstrates best practices for handling multiple output formats and managing transient resources that can be read after the tool completes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 0d01c5f commit b7c1428

File tree

1 file changed

+56
-13
lines changed

1 file changed

+56
-13
lines changed

mcp-server/src/services/mcp.ts

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ const ZipResourcesInputSchema = z.object({
8484
files: z
8585
.record(z.string().url().describe("URL of the file to include in the zip"))
8686
.describe("Mapping of file names to URLs to include in the zip"),
87+
outputType: z
88+
.enum(["resourceLink", "inlinedResourceLink", "resource"])
89+
.default("inlinedResourceLink")
90+
.describe(
91+
"How the resulting zip file should be returned. 'resourceLink' returns a link to a resource that can be read later, 'inlinedResourceLink' returns a resource_link with a data URI, and 'resource' returns a full resource object."
92+
),
8793
});
8894

8995
enum ToolName {
@@ -126,6 +132,7 @@ export const createMcpServer = (): McpServerWrapper => {
126132
);
127133

128134
const subscriptions: Set<string> = new Set();
135+
const transientResources: Map<string, Resource> = new Map();
129136

130137
// Set up update interval for subscribed resources
131138
const subsUpdateInterval = setInterval(() => {
@@ -269,6 +276,12 @@ export const createMcpServer = (): McpServerWrapper => {
269276
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
270277
const uri = request.params.uri;
271278

279+
if (transientResources.has(uri)) {
280+
return {
281+
contents: [transientResources.get(uri)!],
282+
};
283+
}
284+
272285
if (uri.startsWith("test://static/resource/")) {
273286
const index = parseInt(uri.split("/").pop() ?? "", 10) - 1;
274287
if (index >= 0 && index < ALL_RESOURCES.length) {
@@ -639,7 +652,7 @@ export const createMcpServer = (): McpServerWrapper => {
639652
}
640653

641654
if (name === ToolName.ZIP_RESOURCES) {
642-
const { files } = ZipResourcesInputSchema.parse(args);
655+
const { files, outputType } = ZipResourcesInputSchema.parse(args);
643656

644657
const zip = new JSZip();
645658

@@ -660,19 +673,49 @@ export const createMcpServer = (): McpServerWrapper => {
660673
}
661674
}
662675

663-
const uri = `data:application/zip;base64,${await zip.generateAsync({
664-
type: "base64",
665-
})}`;
676+
const blob = await zip.generateAsync({ type: "base64" });
677+
const mimeType = "application/zip";
666678

667-
return {
668-
content: [
669-
{
670-
type: "resource_link",
671-
mimeType: "application/zip",
672-
uri,
673-
},
674-
],
675-
};
679+
if (outputType === "inlinedResourceLink") {
680+
const uri = `data:${mimeType};base64,${blob}`;
681+
return {
682+
content: [
683+
{
684+
type: "resource_link",
685+
mimeType,
686+
uri,
687+
},
688+
],
689+
};
690+
} else {
691+
const name = `out_${Date.now()}.zip`;
692+
const uri = `resource://${name}`;
693+
const resource: Resource = { uri, name, mimeType, blob };
694+
695+
if (outputType === "resource") {
696+
return {
697+
content: [
698+
{
699+
type: "resource",
700+
resource,
701+
},
702+
],
703+
};
704+
} else if (outputType === "resourceLink") {
705+
transientResources.set(uri, resource);
706+
return {
707+
content: [
708+
{
709+
type: "resource_link",
710+
mimeType,
711+
uri,
712+
},
713+
],
714+
};
715+
} else {
716+
throw new Error(`Unknown outputType: ${outputType}`);
717+
}
718+
}
676719
}
677720

678721
throw new Error(`Unknown tool: ${name}`);

0 commit comments

Comments
 (0)