[Add] Synaptic AI Pro
https://assetstore.unity.com/packages/tools/generative-ai/synaptic-ai-pro-natural-language-control-for-unity-336030
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
const { Server } = require('@modelcontextprotocol/sdk/server/index.js');
|
||||
const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
|
||||
const {
|
||||
ListToolsRequestSchema,
|
||||
CallToolRequestSchema,
|
||||
ListResourcesRequestSchema,
|
||||
ReadResourceRequestSchema
|
||||
} = require('@modelcontextprotocol/sdk/types.js');
|
||||
|
||||
// Zodスキーマを MCP JSON Schema に変換
|
||||
function convertZodSchemaToMCP(zodSchema) {
|
||||
if (!zodSchema || !zodSchema._def) return {};
|
||||
|
||||
const def = zodSchema._def;
|
||||
|
||||
if (def.typeName === 'ZodObject') {
|
||||
const properties = {};
|
||||
const required = [];
|
||||
|
||||
for (const [key, value] of Object.entries(def.shape())) {
|
||||
properties[key] = convertZodSchemaToMCP(value);
|
||||
if (!value.isOptional()) {
|
||||
required.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'object',
|
||||
properties,
|
||||
required: required.length > 0 ? required : undefined
|
||||
};
|
||||
}
|
||||
|
||||
if (def.typeName === 'ZodString') {
|
||||
return { type: 'string' };
|
||||
}
|
||||
|
||||
if (def.typeName === 'ZodNumber') {
|
||||
return { type: 'number' };
|
||||
}
|
||||
|
||||
if (def.typeName === 'ZodBoolean') {
|
||||
return { type: 'boolean' };
|
||||
}
|
||||
|
||||
if (def.typeName === 'ZodArray') {
|
||||
return {
|
||||
type: 'array',
|
||||
items: convertZodSchemaToMCP(def.type)
|
||||
};
|
||||
}
|
||||
|
||||
if (def.typeName === 'ZodEnum') {
|
||||
return {
|
||||
type: 'string',
|
||||
enum: def.values
|
||||
};
|
||||
}
|
||||
|
||||
if (def.typeName === 'ZodOptional') {
|
||||
return convertZodSchemaToMCP(def.innerType);
|
||||
}
|
||||
|
||||
if (def.typeName === 'ZodDefault') {
|
||||
const schema = convertZodSchemaToMCP(def.innerType);
|
||||
schema.default = def.defaultValue();
|
||||
return schema;
|
||||
}
|
||||
|
||||
if (def.typeName === 'ZodAny') {
|
||||
return {}; // Any type - no restrictions
|
||||
}
|
||||
|
||||
if (def.typeName === 'ZodRecord') {
|
||||
return { type: 'object' };
|
||||
}
|
||||
|
||||
return { type: 'string' };
|
||||
}
|
||||
|
||||
function createServer() {
|
||||
const registeredTools = {};
|
||||
const registeredResources = {};
|
||||
|
||||
const server = new Server(
|
||||
{
|
||||
name: 'unity-mcp',
|
||||
version: '1.1.0',
|
||||
},
|
||||
{
|
||||
capabilities: {
|
||||
resources: {},
|
||||
tools: {},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// ツール一覧を返すハンドラー
|
||||
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
return {
|
||||
tools: Object.entries(registeredTools).map(([name, tool]) => ({
|
||||
name,
|
||||
description: tool.description,
|
||||
inputSchema: tool.inputSchema
|
||||
}))
|
||||
};
|
||||
});
|
||||
|
||||
// ツール実行ハンドラー
|
||||
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
const { name, arguments: args } = request.params;
|
||||
|
||||
if (!registeredTools[name]) {
|
||||
throw new Error(`Unknown tool: ${name}`);
|
||||
}
|
||||
|
||||
const tool = registeredTools[name];
|
||||
|
||||
try {
|
||||
// Zodでバリデーション
|
||||
if (tool.zodSchema) {
|
||||
tool.zodSchema.parse(args);
|
||||
}
|
||||
|
||||
const result = await tool.handler(args);
|
||||
return result;
|
||||
} catch (error) {
|
||||
// エラーログを標準エラー出力に出さない(JSON-RPC通信を妨害するため)
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
|
||||
// リソース一覧を返すハンドラー
|
||||
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
||||
return {
|
||||
resources: Object.entries(registeredResources).map(([uri, resource]) => ({
|
||||
uri,
|
||||
name: resource.name,
|
||||
description: resource.description,
|
||||
mimeType: resource.mimeType
|
||||
}))
|
||||
};
|
||||
});
|
||||
|
||||
// リソース読み取りハンドラー
|
||||
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
||||
const { uri } = request.params;
|
||||
|
||||
if (!registeredResources[uri]) {
|
||||
throw new Error(`Unknown resource: ${uri}`);
|
||||
}
|
||||
|
||||
const resource = registeredResources[uri];
|
||||
const result = await resource.handler();
|
||||
return result;
|
||||
});
|
||||
|
||||
// ツール登録メソッド
|
||||
server.registerTool = function(name, config, handler) {
|
||||
const inputSchema = convertZodSchemaToMCP(config.inputSchema);
|
||||
|
||||
registeredTools[name] = {
|
||||
description: config.description || config.title,
|
||||
inputSchema,
|
||||
zodSchema: config.inputSchema,
|
||||
handler
|
||||
};
|
||||
|
||||
// ログを標準エラー出力に出さない
|
||||
};
|
||||
|
||||
// リソース登録メソッド
|
||||
server.registerResource = function(uri, config, handler) {
|
||||
registeredResources[uri] = {
|
||||
name: config.title,
|
||||
description: config.description,
|
||||
mimeType: config.mimeType,
|
||||
handler
|
||||
};
|
||||
|
||||
// ログを標準エラー出力に出さない
|
||||
};
|
||||
|
||||
// サーバー起動メソッド
|
||||
server.start = async function() {
|
||||
const transport = new StdioServerTransport();
|
||||
await this.connect(transport);
|
||||
// ログを標準エラー出力に出さない
|
||||
};
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
module.exports = { createServer };
|
||||
Reference in New Issue
Block a user