@solana-agent-kit/adapter-mcp
Version:
Create MCP servers with the Solana Agent Kit
108 lines (107 loc) • 3.13 kB
JavaScript
// src/index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
function isZodOptional(schema) {
return schema instanceof z.ZodOptional;
}
function isZodObject(schema) {
return schema instanceof z.ZodObject || schema?._def?.typeName === "ZodObject";
}
function zodToMCPShape(schema) {
if (!isZodObject(schema)) {
throw new Error("MCP tools require an object schema at the top level");
}
const shape = schema.shape;
const result = {};
for (const [key, value] of Object.entries(shape)) {
result[key] = isZodOptional(value) ? value.unwrap() : value;
}
return {
result,
keys: Object.keys(result)
};
}
function createMcpServer(actions, solanaAgentKit, options) {
const server = new McpServer({
name: options.name,
version: options.version
});
for (const [_key, action] of Object.entries(actions)) {
const { result } = zodToMCPShape(action.schema);
server.tool(action.name, action.description, result, async (params) => {
try {
const result2 = await action.handler(solanaAgentKit, params);
return {
content: [
{
type: "text",
text: JSON.stringify(result2, null, 2)
}
]
};
} catch (error) {
console.error("error", error);
return {
isError: true,
content: [
{
type: "text",
text: error instanceof Error ? error.message : "Unknown error occurred"
}
]
};
}
});
if (action.examples && action.examples.length > 0) {
server.prompt(
`${action.name}-examples`,
{
showIndex: z.string().optional().describe("Example index to show (number)")
},
(args) => {
const showIndex = args.showIndex ? parseInt(args.showIndex) : void 0;
const examples = action.examples.flat();
const selectedExamples = typeof showIndex === "number" ? [examples[showIndex]] : examples;
const exampleText = selectedExamples.map(
(ex, idx) => `
Example ${idx + 1}:
Input: ${JSON.stringify(ex.input, null, 2)}
Output: ${JSON.stringify(ex.output, null, 2)}
Explanation: ${ex.explanation}
`
).join("\n");
return {
messages: [
{
role: "user",
content: {
type: "text",
text: `Examples for ${action.name}:
${exampleText}`
}
}
]
};
}
);
}
}
return server;
}
async function startMcpServer(actions, solanaAgentKit, options) {
try {
const server = createMcpServer(actions, solanaAgentKit, options);
const transport = new StdioServerTransport();
await server.connect(transport);
return server;
} catch (error) {
console.error("Error starting MCP server", error);
throw error;
}
}
export {
createMcpServer,
startMcpServer,
zodToMCPShape
};