Аз съм доста пристрастен към последния от нас сериал. Съжалявам за корицата. MCPs са навсякъде и по добра причина.Това е следващата стъпка в еволюцията на приложенията. Да можеш да използваш всичко от един чат, без да имаш достъп до което и да е приложение. да планирате всичките си социални постове от чата! Така че започнах да копая в кода на Postiz и добавих към него! Постът на Репозиторията на MCP е малко странна Всеки MCP има транспорт, който е методът, който LLMs използват, за да говорят с нашата система. Stdio, което по същество е командна линия, и SSE. There are two primary methods at the moment Не разбирам защо са избрали SSE – това е основно дълго искане, което никога не свършва и предава събития на клиента. Проблемът с този метод е, че за да изпратите информация обратно на сървъра, трябва да изпратите друго искане за поща (тъй като SSE е еднопосочна комуникация), което означава, че трябва да запазите състоянието. В примера си те държат състоянието в паметта на приложението и предполагат какво?Много хора се оплакват от изтичане на памет, защото състоянието не се изтрива, когато потребителят се изключи. Ще използвам WebSockets. Те имат вграден режим на сън и не е нужно да поддържате състояние за него. Изкопаване на Изкопах в Anthropic typcript SDK и не бях изненадан. Чувства се грозно. Много неща не се използват в производството, като "Ресурси". Начинът, по който те изискват от вас да запазите всичко глобално в паметта, е бедствие, което чака да се случи. Също така е трудно да се реализира удостоверяване и да се извади потребителя от контекста, за да можем да получим техните подробности. Postiz е изграден с NestJS, така че когато използвате маршрут на SSE, той затваря наблюдаваното, след като се изключи, което ви позволява да премахнете всичко от паметта. import EventEmitter from 'events'; import { finalize, fromEvent, startWith } from 'rxjs'; @Injectable() export class McpService { static event = new EventEmitter(); constructor( private _mainMcp: MainMcp ) { } async runServer(apiKey: string, organization: string) { const server = McpSettings.load(organization, this._mainMcp).server(); const transport = new McpTransport(organization); const observer = fromEvent( McpService.event, `organization-${organization}` ).pipe( startWith({ type: 'endpoint', data: process.env.NEXT_PUBLIC_BACKEND_URL + '/mcp/' + apiKey + '/messages', }), finalize(() => { transport.close(); }) ); console.log('MCP transport started'); await server.connect(transport); return observer; } async processPostBody(organization: string, body: object) { const server = McpSettings.load(organization, this._mainMcp).server(); const message = JSONRPCMessageSchema.parse(body); const transport = new McpTransport(organization); await server.connect(transport); transport.handlePostMessage(message); return {}; } } Декорация ️ Това е за вас, ако сте голям фен на OOP рамки като NestJS/Laravel/Spring. създадох хладен декоратор за създаване на инструменти като API "крайни точки". @McpTool({ toolName: 'POSTIZ_GET_CONFIG_ID' }) async preRun() { return [ { type: 'text', text: `id: ${makeId(10)} Today date is ${dayjs.utc().format()}`, }, ]; } @McpTool({ toolName: 'POSTIZ_PROVIDERS_LIST' }) async listOfProviders(organization: string) { const list = ( await this._integrationService.getIntegrationsList(organization) ).map((org) => ({ id: org.id, name: org.name, identifier: org.providerIdentifier, picture: org.picture, disabled: org.disabled, profile: org.profile, customer: org.customer ? { id: org.customer.id, name: org.customer.name, } : undefined, })); return [{ type: 'text', text: JSON.stringify(list) }]; } @McpTool({ toolName: 'POSTIZ_SCHEDULE_POST', zod: { type: eenum(['draft', 'scheduled']), configId: string(), generatePictures: boolean(), date: string().describe('UTC TIME'), providerId: string().describe('Use POSTIZ_PROVIDERS_LIST to get the id'), posts: array(object({ text: string(), images: array(string()) })), }, }) async schedulePost( organization: string, obj: { type: 'draft' | 'schedule'; generatePictures: boolean; date: string; providerId: string; posts: { text: string }[]; } ) { const create = await this._postsService.createPost(organization, { date: obj.date, type: obj.type, tags: [], posts: [ { group: makeId(10), value: await Promise.all( obj.posts.map(async (post) => ({ content: post.text, id: makeId(10), image: !obj.generatePictures ? [] : [ { id: makeId(10), path: await this._openAiService.generateImage( post.text, true ), }, ], })) ), // @ts-ignore settings: {}, integration: { id: obj.providerId, }, }, ], }); return [ { type: 'text', text: `Post created successfully, check it here: ${process.env.FRONTEND_URL}/p/${create[0].postId}`, }, ]; } Целият код може да бъде намерен в Postiz тук: https://github.com/gitroomhq/postiz-app/tree/main/libraries/nestjs-libraries/src/mcp И тук: https://github.com/gitroomhq/postiz-app/tree/main/apps/backend/src/mcp Накарайте LLM да направи нещата 🙏🏻 Би било хубаво да имаме вградена опция, за да принудим LLM да прави различни неща, преди да получи достъп до нашите неща. Всеки път, когато казах на Cursor да планира пост за мен, той се опита да го планира за 2024 г. Това е последният път, когато моделът беше обучен. Трябваше да премина някои конфиг детайли, така че създадох Надявам се, че LLM винаги ще го нарича, преди да направи нещо. POSTIZ_CONFIGURATION_PRERUN Но тя го игнорира много пъти (типично), така че трябваше да бъда творчески. , добавих нова собственост, наречена и променете името на инструмента Config на Резултатът от конфигурацията е: POSTIZ_SCHEDULE_POST configId POSTIZ_GET_CONFIG_ID. id: ${makeId(10)} Today date is ${dayjs.utc().format()} Това принуди LLM винаги да го нарича по-рано, а датата беше фиксирана! :) Това беше още по-добре за мен, защото знаех, че ще ми изпрати UTC дати отсега нататък. Случаи на употреба Мисля, че тя работи най-добре, когато се комбинира с няколко набора от инструменти, например: на на на на Свържете го с курсора и го помолете да планира публикация за вашата работа днес. Свържете го с Notion и поискайте да планирате цялата последна работа на екипа в социалните медии - вижте Composio MCPs. Свържете го с всяка SaaS, която има CopilotKit и планирайте публикации въз основа на приложението. Създаване на MCP е най-трайният инструмент за планиране на социални медии с отворен код - и сега единственият графика, който предлага MCP (натурално, не със Zapier или нещо подобно) Постът С новия MCP можете да планирате всичките си публикации от клиентите Cursor/Windsurf и Anthropic. Всичко е 100% безплатно :) Ако ви харесва, не забравяйте да ни звезда ⭐️ https://github.com/gitroomhq/postiz-апп